diff --git a/libraries/ASR5801/ASR5801 datasheet.pdf b/libraries/ASR5801/ASR5801 datasheet.pdf new file mode 100644 index 0000000..c7880b0 Binary files /dev/null and b/libraries/ASR5801/ASR5801 datasheet.pdf differ diff --git a/libraries/AW8733ATQR/AW8733ATQR.pdf b/libraries/AW8733ATQR/AW8733ATQR.pdf new file mode 100644 index 0000000..758e434 Binary files /dev/null and b/libraries/AW8733ATQR/AW8733ATQR.pdf differ diff --git "a/libraries/AW9523B/C148077_I-O\346\211\251\345\261\225\345\231\250_AW9523BTQR_\350\247\204\346\240\274\344\271\246_AWINIC(\350\211\276\344\270\272)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" "b/libraries/AW9523B/C148077_I-O\346\211\251\345\261\225\345\231\250_AW9523BTQR_\350\247\204\346\240\274\344\271\246_AWINIC(\350\211\276\344\270\272)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" new file mode 100644 index 0000000..650c70d Binary files /dev/null and "b/libraries/AW9523B/C148077_I-O\346\211\251\345\261\225\345\231\250_AW9523BTQR_\350\247\204\346\240\274\344\271\246_AWINIC(\350\211\276\344\270\272)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" differ diff --git a/libraries/AW9523B/aw9523.py b/libraries/AW9523B/aw9523.py new file mode 100644 index 0000000..4b7a55f --- /dev/null +++ b/libraries/AW9523B/aw9523.py @@ -0,0 +1,274 @@ +# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +@file :aw9523.py +@author :Jack Sun (jack.sun@quectel.com) +@brief : +@version :1.0.0 +@date :2023-02-01 09:21:44 +@copyright :Copyright (c) 2022 +""" + +from queue import Queue +from machine import ExtInt +from usr.logging import Logger +from usr.common import create_thread + +log = Logger(__name__) + + +_AW9523_DEFAULT_ADDR_KEY = (0x58) # The key drive address is 0x58, and the IO extension address is 0x5B +_AW9523_DEFAULT_ADDR_IO = (0x5B) +_AW9523_REG_CHIPID = (0x10) # Register for hardcode chip ID +_AW9523_REG_SOFTRESET = (0x7F) # Register for soft resetting +_AW9523_REG_INTENABLE0 = (0x06) # Register for enabling interrupt +_AW9523_REG_GCR = (0x11) # Register for general configuration +_AW9523_REG_LEDMODE = (0x12) # Register for configuring current +_AW9523_REG_INPUT0 = (0x00) # Register for reading input values +_AW9523_REG_OUTPUT0 = (0x02) # Register for writing output values +_AW9523_REG_CONFIG0 = (0x04) # Register for configuring direction + + +class Port(): + # 表示两个8位端口之一 + def __init__(self, port, aw): + self._port = port & 1 # 0=PortA, 1=PortB + self._aw = aw + + def _which_reg(self, reg): + return reg + self._port + + def _flip_property_bit(self, reg, condition, bit): + if condition: + setattr(self, reg, getattr(self, reg) | bit) + else: + setattr(self, reg, getattr(self, reg) & ~bit) + + def _read(self, reg): + r_data = bytearray(1) + self._aw._i2c.read(self._aw._address, bytearray([self._which_reg(reg)]), 1, r_data, 1, 0) + return list(r_data)[0] + + def _write(self, reg, val): + val &= 0xff + self._aw._i2c.write(self._aw._address, bytearray([self._which_reg(reg)]), 1, bytearray([val]), 1) + + @property + def mode(self): + return self._read(_AW9523_REG_CONFIG0) + + @mode.setter + def mode(self, val): + self._write(_AW9523_REG_CONFIG0, val) + + @property + def interrupt_enable(self): + return self._read(_AW9523_REG_INTENABLE0) + + @interrupt_enable.setter + def interrupt_enable(self, val): + # log.debug("val:",bin(val)) + self._write(_AW9523_REG_INTENABLE0, val) + + # read only + @property + def interrupt_flag(self): + return self._read(_AW9523_REG_INPUT0) + + @property + def gpio(self): + return self._read(_AW9523_REG_OUTPUT0) + + @gpio.setter + def gpio(self, val): + # writing to this register modifies the OLAT register for pins configured as output + self._write(_AW9523_REG_OUTPUT0, val) + + +class AW9523: + + # _pin_to_addr = ([0x24 + pin for pin in range(8)] + + # [0x20 + pin - 8 for pin in range(8, 12)] + + # [0x2C + pin - 12 for pin in range(12, 16)]) + + def __init__(self, i2c_bus, int_pin=1, int_mode=0, int_callback=None, address=_AW9523_DEFAULT_ADDR_KEY): + self._i2c = i2c_bus + self._int_pin = int_pin + self._int_mode = int_mode + self._address = address + self._int_callback = int_callback + self.__ext_thread_id = None + self.__ext_queue = Queue() + self._ret = 0x001F # 接收电平状态 + + if self._address == _AW9523_DEFAULT_ADDR_KEY: + self._extint = ExtInt(self._int_pin, ExtInt.IRQ_RISING_FALLING, ExtInt.PULL_PU, self.__extfun) + self._extint.enable() + self.__ext_thread_id = create_thread(self.__extfun_thread, stack_size=0x4000) + + # Read device ID. AW9523B ID read default value is 23H + self.read_buf = bytearray(5) + self._i2c.read(address, bytearray((_AW9523_REG_CHIPID, 0xff)), 1, self.read_buf, 1, 20) + # log.debug("read_buff:", self.read_buf) + if (self.read_buf[0] != 0x23): + raise AttributeError("Cannot find a AW9523") + + # self.reset() + self.porta = Port(0, self) + self.portb = Port(1, self) + + def __extfun(self, args): + self.__ext_queue.put(args) + + #执行中断回调 + def __extfun_thread(self): + while 1: + args = self.__ext_queue.get() + log.debug('### interrupt {} ###'.format(args)) + # 读取两组电平,判断触发了中断的io,中断信号前后电平对比 + # status_0 = self._read(_AW9523_REG_INPUT0) + # status_1 = self._read(_AW9523_REG_INPUT0 + 1) + self._i2c.read(_AW9523_DEFAULT_ADDR_KEY, bytearray((_AW9523_REG_INPUT0, 0xff)), 1, self.read_buf, 1, 20) + status_0 = self.read_buf[0] + self._i2c.read(_AW9523_DEFAULT_ADDR_KEY, bytearray((_AW9523_REG_INPUT0 + 1, 0xff)), 1, self.read_buf, 1, 20) + status_1 = self.read_buf[0] + status = (status_1 << 8) | status_0 + # log.debug('### io level {} ###'.format(bin(status))) + + change = (self._ret ^ status) + if self._int_callback is None: + return + + #byte 引脚号 pin_level 电平 + if change is not 0: + byte = 0 + pin_level = 1 + while byte < 16: + if (change & (1 << byte)): + break + else: + byte = byte + 1 + + if (status & (1 << byte)): + pin_level = 1 + else: + pin_level = 0 + + #判断是否该IO是否中断使能 + # flag_0 = self._read(_AW9523_REG_INTENABLE0) + # flag_1 = self._read(_AW9523_REG_INTENABLE0 + 1) + self._i2c.read(_AW9523_DEFAULT_ADDR_KEY, bytearray((_AW9523_REG_INTENABLE0, 0xff)), 1, self.read_buf, 1, 20) + flag_0 = self.read_buf[0] + self._i2c.read(_AW9523_DEFAULT_ADDR_KEY, bytearray((_AW9523_REG_INTENABLE0 + 1, 0xff)), 1, self.read_buf, 1, 20) + flag_1 = self.read_buf[0] + flag = (flag_1 << 8) | flag_0 + if flag & (1 << byte) == 0: + list_push = [byte, pin_level] + self._int_callback(list_push) + # log.debug('### io level {} ###'.format(bin(status))) + # 保存上一次电平状态 + self._ret = status + + def _read(self, addr): + r_data = bytearray(1) + self._i2c.read(self._address, bytearray([addr]), 1, r_data, 1, 20) + return list(r_data)[0] + + def _write(self, addr, *vals): + # log.debug("write vals:", vals) + self._i2c.write(self._address, bytearray([addr]), 1, bytearray(list(vals)), len(list(vals))) + + def reset(self): + self._write(_AW9523_REG_SOFTRESET, 0x00) # 对该寄存器写 00H 复位 reset + self._write(_AW9523_REG_GCR, 0b00010000) # pushpull output D[4]=0,Open-Drain模式; D[4]=1,Push-Pull模式 + self._write(_AW9523_REG_INTENABLE0, 0xff, 0xff) # no IRQ 0-中断使能; 1-中断不使能 + self._write(_AW9523_REG_INTENABLE0 + 1, 0xff, 0xff) # no IRQ + # self._write(_AW9523_REG_LEDMODE, 0xff, 0xff) #gpio mode + # self._write(_AW9523_REG_LEDMODE+1, 0xff, 0xff) #gpio mode + + # set aw9523 pin + def pin(self, pin, mode=None, value=None, interrupt_enable=None): + assert 0 <= pin <= 15 + port = self.portb if pin // 8 else self.porta + bit = (1 << (pin % 8)) + if mode is not None: + # 0: Pin is configured as an output + # 1: Pin is configured as an input + port._flip_property_bit('mode', mode & 1, bit) + if value is not None: + # 0: 引脚设置为逻辑低电平 + # 1: 引脚设置为逻辑高电平 + port._flip_property_bit('gpio', value & 1, bit) + if interrupt_enable is not None: + # 1: Disables GPIO input pin for interrupt-on-change event + # 0: Enables GPIO input pin for interrupt-on-change event + if interrupt_enable == 0: + interrupt_enable = 1 + else: + interrupt_enable = 0 + port._flip_property_bit('interrupt_enable', interrupt_enable & 1, bit) + if value is None: + return port.gpio & bit == bit + + # mode (IODIR register) + @property + def mode(self): + return self.porta.mode | (self.portb.mode << 8) + + @mode.setter + def mode(self, val): + self.porta.mode = val + self.portb.mode = (val >> 8) + + # interrupt_enable (GPINTEN register) + @property + def interrupt_enable(self): + return self.porta.interrupt_enable | (self.portb.interrupt_enable << 8) + + @interrupt_enable.setter + def interrupt_enable(self, val): + self.porta.interrupt_enable = val + self.portb.interrupt_enable = (val >> 8) + + # interrupt_flag (INTF register) + # read only + @property + def interrupt_flag(self): + return self.porta.interrupt_flag | (self.portb.interrupt_flag << 8) + + # gpio (GPIO register) + @property + def gpio(self): + return self.porta.gpio | (self.portb.gpio << 8) + + @gpio.setter + def gpio(self, val): + self.porta.gpio = val + self.portb.gpio = (val >> 8) + + # 获取引脚电平,pin为引脚号0~15 + def read(self, pin): + status_0 = self._read(_AW9523_REG_INPUT0) + status_1 = self._read(_AW9523_REG_INPUT0 + 1) + status = (status_1 << 8) | status_0 + pin_level = 0 + if (status & (1 << pin)): + pin_level = 1 + else: + pin_level = 0 + return pin_level diff --git a/libraries/BF3901/BF3901CS.pdf b/libraries/BF3901/BF3901CS.pdf new file mode 100644 index 0000000..58f2e01 Binary files /dev/null and b/libraries/BF3901/BF3901CS.pdf differ diff --git a/libraries/BM8563/Belling-BM8563.pdf b/libraries/BM8563/Belling-BM8563.pdf new file mode 100644 index 0000000..42ed135 Binary files /dev/null and b/libraries/BM8563/Belling-BM8563.pdf differ diff --git a/libraries/BME280/BME280_datasheet.pdf b/libraries/BME280/BME280_datasheet.pdf new file mode 100644 index 0000000..b8e1db2 Binary files /dev/null and b/libraries/BME280/BME280_datasheet.pdf differ diff --git "a/libraries/CST816/CST816S\346\225\260\346\215\256\346\211\213\345\206\214V1.1.pdf" "b/libraries/CST816/CST816S\346\225\260\346\215\256\346\211\213\345\206\214V1.1.pdf" new file mode 100644 index 0000000..01fade6 Binary files /dev/null and "b/libraries/CST816/CST816S\346\225\260\346\215\256\346\211\213\345\206\214V1.1.pdf" differ diff --git a/libraries/ESP8266/0a-esp8266ex_datasheet_en.pdf b/libraries/ESP8266/0a-esp8266ex_datasheet_en.pdf new file mode 100644 index 0000000..6ab0e6c Binary files /dev/null and b/libraries/ESP8266/0a-esp8266ex_datasheet_en.pdf differ diff --git a/libraries/ESP8266/esp8266.py b/libraries/ESP8266/esp8266.py new file mode 100644 index 0000000..27948be --- /dev/null +++ b/libraries/ESP8266/esp8266.py @@ -0,0 +1,114 @@ +import slip +import dataCall +import utime +import usocket +import checkNet +from machine import UART +from usr.common_except import CustomError + +class Esp8266(object): + def __init__(self): + self._wait_datacall_success() + + def _wait_datacall_success(self): + print('waiting datacall success...') + while 1: + self.lteInfo = dataCall.getInfo(1, 0) + if self.lteInfo != -1: + break + utime.sleep(2) + print('success get dataCall info: ') + print(self.lteInfo) + +class Esp8266_ap(Esp8266): + ESP_SERVER = '172.16.1.5' + ESP_SERVER_PORT = 1000 + + def __init__(self,uart): + super().__init__() + self.wifi_off() + # 创建slip网卡 + ret = slip.construct(uart, slip.SLIP_INNER, 0) + print(ret) + if ret != 0: + raise CustomError("slip netif construct fail") + + def _pack_tlv_format(self,head, content): + if len(content) == 0 or len(content) > 9999 or len(head) != 2: + print('illegal tlv content') + return 0 + len_str = '%04d' % len(content) + msg = head + len_str + content + return msg + + def wifi_on(self): + # 获取slip的网络配置 + slipInfo = slip.ipconfig() + print('slip ipconfig: ') + print(slipInfo) + if self.lteInfo != -1: + # 设置默认网卡,当设置slip作为上网卡时不设置该接口,即SLIP_OUTER类型 + ret = slip.set_default_netif(self.lteInfo[2][2]) + if ret != 0: + print('slip set default netif fail') + return -1 + # 添加路由信息,设置网卡转发规则192.168.4.0表示ap的网段,255.255.255.0子网掩码 + ret = slip.router_add('192.168.4.0', '255.255.255.0') + if ret != 0: + print('slip add subnet routers fail') + return -1 + return 0 + + def set_ap(self,name=None,pwd=None,project_name='wifi_setap',project_version='1.0.0'): + checknet = checkNet.CheckNetwork(project_name, project_version) + stagecode, subcode = checknet.wait_network_connected(30) + if stagecode != 3 or subcode != 1: + print('fail to set ap. ') + return -1 + # 创建一个socket实例 + sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) + # 增加端口复用 + sock.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1) + # 解析域名 + addr = usocket.getaddrinfo(self.ESP_SERVER, self.ESP_SERVER_PORT) + print(addr) + sockaddr = addr[0][-1] + print(sockaddr) + bind_addr = ('172.16.1.2', 10001) + ret = sock.bind(bind_addr) + print('bind success') + print(ret) + # 建立连接 + sock.connect(sockaddr) + # 向服务端发送消息 + if name == None and pwd == None: + return -1 + elif name == None: + msg = self._pack_tlv_format('F1', pwd) + elif pwd == None: + msg = self._pack_tlv_format('F2', name) + else: + msg = self._pack_tlv_format('F3', name+','+pwd) + print(msg) + ret = sock.send(msg) + print('send %d bytes' % ret) + # 接收服务端消息 + data = sock.recv(256) + print('recv %s bytes:' % len(data)) + print(data.decode()) + + # 关闭连接 + sock.close() + return 0 + + def wifi_off(self): + slip.destroy() + +if __name__=="__main__": + esp8266 = Esp8266_ap(UART.UART2) + esp8266.set_ap(name='大好年华',pwd='11111111') + err = esp8266.wifi_on() + if err == 0: + print('slip network card create success') + else: + print('slip network card create fail') diff --git a/libraries/GC032A/GC032A.pdf b/libraries/GC032A/GC032A.pdf new file mode 100644 index 0000000..b6d488f Binary files /dev/null and b/libraries/GC032A/GC032A.pdf differ diff --git a/libraries/GC032A/gc032a_demo.py b/libraries/GC032A/gc032a_demo.py new file mode 100644 index 0000000..ad05904 --- /dev/null +++ b/libraries/GC032A/gc032a_demo.py @@ -0,0 +1,17 @@ +from usr.st7789 import LCD_ST7789 +from usr import CommonCamera +import utime as time + +def cap_callback(LCD): + LCD.Clear(0xFFFF) + time.sleep(2) + LCD._lcd.lcd_show_jpg('/usr/pic_01.jpeg', 0, 0) + +if __name__ == '__main__': + new_lcd = LCD_ST7789() + print("lcd init. ") + my_gc032a = CommonCamera(0,capt_callback=cap_callback) + my_gc032a.cap_open() + time.sleep(1) + my_gc032a.start(name="pic_01") + diff --git a/libraries/GC6133/GC6133 Datasheet V1.01_20151201.pdf b/libraries/GC6133/GC6133 Datasheet V1.01_20151201.pdf new file mode 100644 index 0000000..d6242c2 Binary files /dev/null and b/libraries/GC6133/GC6133 Datasheet V1.01_20151201.pdf differ diff --git a/libraries/GT9XX/GT911 Datasheet_20130319.pdf b/libraries/GT9XX/GT911 Datasheet_20130319.pdf new file mode 100644 index 0000000..a3bad07 Binary files /dev/null and b/libraries/GT9XX/GT911 Datasheet_20130319.pdf differ diff --git a/libraries/ICM20948/ICM-20948-v1.3.pdf b/libraries/ICM20948/ICM-20948-v1.3.pdf new file mode 100644 index 0000000..f8194c1 Binary files /dev/null and b/libraries/ICM20948/ICM-20948-v1.3.pdf differ diff --git a/libraries/JLSEMI_JL11x1/JLSEMI_JL11x1-v1.11.pdf b/libraries/JLSEMI_JL11x1/JLSEMI_JL11x1-v1.11.pdf new file mode 100644 index 0000000..e16dc63 Binary files /dev/null and b/libraries/JLSEMI_JL11x1/JLSEMI_JL11x1-v1.11.pdf differ diff --git a/libraries/L76K/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf b/libraries/L76K/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf new file mode 100644 index 0000000..8a8bbda Binary files /dev/null and b/libraries/L76K/Quectel_L76K_GNSS_Protocol_Specification_V1.1.pdf differ diff --git "a/libraries/L76K/Quectel_L76K_GNSS_\346\250\241\345\235\227\344\272\247\345\223\201\350\247\204\346\240\274\344\271\246_V1.4.pdf" "b/libraries/L76K/Quectel_L76K_GNSS_\346\250\241\345\235\227\344\272\247\345\223\201\350\247\204\346\240\274\344\271\246_V1.4.pdf" new file mode 100644 index 0000000..b074d59 Binary files /dev/null and "b/libraries/L76K/Quectel_L76K_GNSS_\346\250\241\345\235\227\344\272\247\345\223\201\350\247\204\346\240\274\344\271\246_V1.4.pdf" differ diff --git a/libraries/L76K/gnss.py b/libraries/L76K/gnss.py new file mode 100644 index 0000000..21d8b83 --- /dev/null +++ b/libraries/L76K/gnss.py @@ -0,0 +1,122 @@ +from gnss import GnssGetData +import utime + +class Gnss(object): + def __init__(self,uartn,baudrate,databits,parity,stopbits,flowctl): + self._gnss = GnssGetData(uartn, baudrate, databits, parity, stopbits, flowctl) + + def read_gnss(self,retry = 1,debug = 0): + ''' + 读取GNSS数据 + :param retry: 重试次数 + :param debug: 输出调试信息 + :return: -1 失败 + (有效位,原始GNSS数据) 成功 + 有效位(0x01-0x07): 0x04 gga有效 + 0x02 rmc有效 + 0x01 gsv有效, + ''' + self._gnss.read_gnss_data(retry,debug) + gga_valid, rmc_valid, gsv_valid = self._gnss.checkDataValidity() + data = self._gnss.getOriginalData() + data_valid = 0x00 + if not (gga_valid | rmc_valid | gsv_valid): + return -1 + if gga_valid: + data_valid |= 0x04 + if rmc_valid: + data_valid |= 0x02 + if gsv_valid: + data_valid |= 0x01 + return (data_valid,data) + + def isFix(self): + ''' + 检查是否定位成功 + :return:1:定位成功 0:失败 + ''' + return self._gnss.isFix() + + def getUtcTime(self): + ''' + 获取定位的UTC时间 + :return:成功返回UTC时间,字符串类型,失败返回整型-1。 + ''' + return self._gnss.getUtcTime() + + def getLocationMode(self): + ''' + 获取GPS模块定位模式 + :return: -1 获取失败,串口未读到数据或未读到有效数据 + 0 定位不可用或者无效 + 1 定位有效,定位模式:GPS、SPS 模式 + 2 定位有效,定位模式: DGPS、DSPS 模式 + 6 估算(航位推算)模式 + ''' + return self._gnss.getLocationMode() + + def getUsedSateCnt(self): + ''' + 获取GPS模块定位使用卫星数量 + :return:成功返回GPS模块定位使用卫星数量,返回值类型为整型,失败返回整型-1。 + ''' + return self._gnss.getUsedSateCnt() + + def getLocation(self): + ''' + 获取GPS模块定位的经纬度信息 + :return:成功返回GPS模块定位的经纬度信息,失败返回整型-1;成功时返回值格式如下: + (longitude, lon_direction, latitude, lat_direction) + longitude - 经度,float型 + lon_direction - 经度方向,字符串类型,E表示东经,W表示西经 + latitude - 纬度,float型 + lat_direction - 纬度方向,字符串类型,N表示北纬,S表示南纬 + ''' + return self._gnss.getLocation() + + def getViewedSateCnt(self): + ''' + 获取GPS模块定位可见卫星数量 + :return:成功返回GPS模块定位可见卫星数量,整型值,失败返回整型-1。 + ''' + return self._gnss.getViewedSateCnt() + + def getGeodeticHeight(self): + ''' + 获取GPS模块定位海拔高度 + :return:成功返回浮点类型海拔高度(单位:米),失败返回整型-1。 + ''' + return self._gnss.getGeodeticHeight() + + def getCourse(self): + ''' + 获取可视的GNSS卫星方位角 + :return:返回所有可视的GNSS卫星方位角,范围:0 ~ 359,以正北为参考平面。 + 返回形式为字典,其中key表示卫星编号,value表示方位角。 + 要注意,value的值可能是一个整型值,也可能是'',这取决于原始的GNSS数据中GPGSV语句中方位角是否有值。 + ''' + return self._gnss.getCourse() + + def getSpeed(self): + ''' + 获取GPS模块对地速度 + :return:成功返回GPS模块对地速度(单位:KM/h),浮点类型,失败返回整型-1 + ''' + return self._gnss.getSpeed() + +if __name__ == "__main__": + gnss = Gnss(1, 9600, 8, 0, 1, 0) + for i in range(10): + print("开始读取GNSS数据") + print(gnss.read_gnss(retry=3)) + utime.sleep(1) + print("定位是否成功 {}".format(gnss.isFix())) + print("定位时间 {}".format(gnss.getUtcTime())) + print("GPS定位模式 {}".format(gnss.getLocationMode())) + print("GPS使用卫星数量 {}".format(gnss.getUsedSateCnt())) + print("GPS位置 {}".format(gnss.getLocation())) + print("GPS模块定位可见卫星数量 {}".format(gnss.getViewedSateCnt())) + print("GPS模块定位海拔高度 {}".format(gnss.getGeodeticHeight())) + print("获取可视的GNSS卫星方位角 {}".format(gnss.getCourse())) + print("获取GPS模块对地速度 {}".format(gnss.getSpeed())) + utime.sleep(1) diff --git a/libraries/LCD/CH1116/CH1116 V0.2.pdf b/libraries/LCD/CH1116/CH1116 V0.2.pdf new file mode 100644 index 0000000..757964f Binary files /dev/null and b/libraries/LCD/CH1116/CH1116 V0.2.pdf differ diff --git a/libraries/LCD/JD91651z/JD9161Z_DS_Preliminary_V0.01_20180803(1).pdf b/libraries/LCD/JD91651z/JD9161Z_DS_Preliminary_V0.01_20180803(1).pdf new file mode 100644 index 0000000..b4ab153 Binary files /dev/null and b/libraries/LCD/JD91651z/JD9161Z_DS_Preliminary_V0.01_20180803(1).pdf differ diff --git a/libraries/LTR-303ALS-01/Itr_303als.py b/libraries/LTR-303ALS-01/Itr_303als.py new file mode 100644 index 0000000..90ea6ab --- /dev/null +++ b/libraries/LTR-303ALS-01/Itr_303als.py @@ -0,0 +1,131 @@ +''' +File: i2c_ltr_303als.py +Project: i2c +File Created: Thursday, 10th March 2022 3:55:22 pm +Author: elian.wang + +----- +Copyright 2022 - 2022 quectel +''' + +from machine import ExtInt +from machine import I2C +#from machine import I2C_simulation +import utime as time +from machine import ExtInt + + +class itl_303als(): + i2c_log = None + i2c_dev = None + i2c_addre = 0x29 + + IRQ_RISING = 0 + IRQ_FALLING = 1 + + light_value = [0, 0] + # ALS operation mode control SW reset + CONTR_ADDR = 0x80 + # ALS measurement rate in active mode + MEAS_RATE_ADDR = 0x85 + # ALS measurement CH1 data, lower byte + DATA_CH1_LOW_ADDR = 0x88 + # ALS measurement CH1 data, upper byte + DATA_CH1_HIGH_ADDR = 0x89 + DATA_CH0_LOW_ADDR = 0x8A + DATA_CH0_HIGH_ADDR = 0x8B + # ALS new data status + STATUS_ADDR = 0x8C + # Interrupt settings + INTERRUPT_ADDR = 0x8F + # ALS interrupt upper threshold, lower byte + THRES_UP_LOW_ADDR = 0x97 + # ALS interrupt upper threshold, upper byte + THRES_UP_HIGH_ADDR = 0x98 + INTERRUPT_PERSIST_ADDR = 0x9E + + def __init__(self, GPIOn, threshod, user_cb, intr_output_mode=IRQ_RISING): + self.cb = user_cb + self.up_threshod = threshod + #self.i2c_log = log.getLogger(Alise) + self.i2c_dev = I2C(I2C.I2C0, I2C.FAST_MODE) # 返回i2c对象 + + if intr_output_mode == 0: + self.extint = ExtInt(GPIOn, ExtInt.IRQ_RISING , ExtInt.PULL_DISABLE , self.ext_cb) + # Enable Interrupt,INT pin is considered active when it is a logic 1 + print('INTERRUPT_ADDR: {}'.format([0x0E])) + self._write([self.INTERRUPT_ADDR], [0x0E]) + + elif intr_output_mode == 1: + self.extint = ExtInt(GPIOn, ExtInt.IRQ_FALLING , ExtInt.PULL_PU , self.ext_cb) + # Enable Interrupt,INT pin is considered active when it is a logic 0 + print('INTERRUPT_ADDR: {}'.format([0x0A])) + self._write([self.INTERRUPT_ADDR], [0x0A]) + else: + raise Exception('set gpio trigger mode fault') + self.extint.enable() + # Enable ALS + self._write([self.CONTR_ADDR], [0x01]) + time.sleep_ms(20) # at last 10ms + + # Set ALS Integration Time 200ms, Repeat Rate 200ms + self._write([self.MEAS_RATE_ADDR], [0x12]) + # Setthe upper limit of the interrupt threshold value 0x5DC + self._write([self.THRES_UP_LOW_ADDR], [self.up_threshod]) + self._write([self.THRES_UP_HIGH_ADDR], [self.up_threshod >> 8]) + # 10 consecutive ALS values out of threshold range + self._write([self.INTERRUPT_PERSIST_ADDR], [0x0A]) + + def _write(self, reg_addr, data): + ret = self.i2c_dev.write(self.i2c_addre, + bytearray(reg_addr), 1, + bytearray(data), len(data)) + print('ret: {}'.format(ret)) + + def _read(self, reg_addr, length): + r_data = [0x00 for i in range(length)] + r_data = bytearray(r_data) + ret = self.i2c_dev.read(self.i2c_addre, + bytearray(reg_addr), 1, + r_data, length, + 0) + if ret == -1: + return [] + else: + return list(r_data) + + def ext_cb(self, args): + self.cb(self.read()) + + def reset(self): + self._write([self.CONTR_ADDR], [0x02]) + time.sleep_ms(20) # at last 20ms + + def read(self): + # Judge ALS data valid + als_sta = self._read([self.STATUS_ADDR], 1) + if len(als_sta) != 0 and (als_sta[0] & 0x80 == 0): + data0 = self._read([self.DATA_CH1_LOW_ADDR], 1) + data1 = self._read([self.DATA_CH1_HIGH_ADDR], 1) + data2 = self._read([self.DATA_CH0_LOW_ADDR], 1) + data3 = self._read([self.DATA_CH0_HIGH_ADDR], 1) + if len(data0) != 0 and len(data1) != 0 and len(data2) != 0 and len(data3) != 0: + self.light_value[0] = (data1[0] << 8) | data0[0] + self.light_value[1] = (data3[0] << 8) | data2[0] + return self.light_value + else: + return [] + else: + return [] + +def user_cb_test(light): + print('light over interrupt {}'.format(light)) + +if __name__ == "__main__": + # GPIO32 GPIO8 + als_dev = itl_303als(ExtInt.GPIO32, 100, user_cb_test, intr_output_mode=itl_303als.IRQ_FALLING) + for i in range(20): + print("test 1 ",i) + print("read data:", als_dev.read()) + time.sleep(1) + diff --git a/libraries/LTR-303ALS-01/LTR-303ALS-01.pdf b/libraries/LTR-303ALS-01/LTR-303ALS-01.pdf new file mode 100644 index 0000000..27b4db7 Binary files /dev/null and b/libraries/LTR-303ALS-01/LTR-303ALS-01.pdf differ diff --git a/libraries/LTR390/1_LTR-390UV_Final_DS_V1_2.pdf b/libraries/LTR390/1_LTR-390UV_Final_DS_V1_2.pdf new file mode 100644 index 0000000..43baa8d Binary files /dev/null and b/libraries/LTR390/1_LTR-390UV_Final_DS_V1_2.pdf differ diff --git a/libraries/MCP23017/MCP23017.pdf b/libraries/MCP23017/MCP23017.pdf new file mode 100644 index 0000000..51e7362 Binary files /dev/null and b/libraries/MCP23017/MCP23017.pdf differ diff --git a/libraries/MCP23017/mcp23017.py b/libraries/MCP23017/mcp23017.py new file mode 100644 index 0000000..e889bc0 --- /dev/null +++ b/libraries/MCP23017/mcp23017.py @@ -0,0 +1,400 @@ +# register addresses in port=0, bank=1 mode (easier maths to convert) +_MCP_IOCON_DEFAULT = 0x0A # R/W Configuration Register 初始为0x0A + +_MCP_IODIR = 0x00 # R/W I/O Direction Register +_MCP_IPOL = 0x01 # R/W Input Polarity Port Register +_MCP_GPINTEN = 0x02 # R/W Interrupt-on-Change Pins +_MCP_DEFVAL = 0x03 # R/W Default Value Register +_MCP_INTCON = 0x04 # R/W Interrupt-on-Change Control Register +_MCP_IOCON = 0x05 # R/W Configuration Register +_MCP_GPPU = 0x06 # R/W Pull-Up Resistor Register +_MCP_INTF = 0x07 # R Interrupt Flag Register (read clears) +_MCP_INTCAP = 0x08 # R Interrupt Captured Value For Port Register +_MCP_GPIO = 0x09 # R/W General Purpose I/O Port Register +_MCP_OLAT = 0x0a # R/W Output Latch Register + +# Config register (IOCON) bits +_MCP_IOCON_INTPOL = 2 +_MCP_IOCON_ODR = 4 +# _MCP_IOCON_HAEN = 8 # no used - for spi flavour of this chip +_MCP_IOCON_DISSLW = 16 +_MCP_IOCON_SEQOP = 32 +_MCP_IOCON_MIRROR = 64 +_MCP_IOCON_BANK = 128 + + +class Port(): + # 表示两个8位端口之一 + def __init__(self, port, mcp): + self._port = port & 1 # 0=PortA, 1=PortB + self._mcp = mcp + + def _which_reg(self, reg): + if self._mcp._config & 0x80 == 0x80: + # bank = 1 + return reg | (self._port << 4) + else: + # bank = 0 + return (reg << 1) + self._port + + def _flip_property_bit(self, reg, condition, bit): + if condition: + setattr(self, reg, getattr(self, reg) | bit) + else: + setattr(self, reg, getattr(self, reg) & ~bit) + + def _read(self, reg): + r_data = bytearray(1) + self._mcp._i2c.read(self._mcp._address, bytearray([self._which_reg(reg)]),1 , r_data, 1, 0) + return list(r_data)[0] + #return self._mcp._i2c.readfrom_mem(self._mcp._address, self._which_reg(reg), 1)[0] + + def _write(self, reg, val): + val &= 0xff + self._mcp._i2c.write(self._mcp._address, bytearray([self._which_reg(reg)]), 1, bytearray([val]),1) + #self._mcp._i2c.writeto_mem(self._mcp._address, self._which_reg(reg), bytearray([val])) + # if writing to the config register, make a copy in mcp so that it knows + # which bank you're using for subsequent writes + if reg == _MCP_IOCON: + self._mcp._config = val + + @property + def mode(self): + return self._read(_MCP_IODIR) + @mode.setter + def mode(self, val): + self._write(_MCP_IODIR, val) + + @property + def input_polarity(self): + return self._read(_MCP_IPOL) + @input_polarity.setter + def input_polarity(self, val): + self._write(_MCP_IPOL, val) + + @property + def interrupt_enable(self): + return self._read(_MCP_GPINTEN) + @interrupt_enable.setter + def interrupt_enable(self, val): + self._write(_MCP_GPINTEN, val) + + @property + def default_value(self): + return self._read(_MCP_DEFVAL) + @default_value.setter + def default_value(self, val): + self._write(_MCP_DEFVAL, val) + + @property + def interrupt_compare_default(self): + return self._read(_MCP_INTCON) + @interrupt_compare_default.setter + def interrupt_compare_default(self, val): + self._write(_MCP_INTCON, val) + + @property + def io_config(self): + return self._read(_MCP_IOCON) + @io_config.setter + def io_config(self, val): + self._write(_MCP_IOCON, val) + + @property + def pullup(self): + return self._read(_MCP_GPPU) + @pullup.setter + def pullup(self, val): + self._write(_MCP_GPPU, val) + + # read only + @property + def interrupt_flag(self): + return self._read(_MCP_INTF) + + # read only + @property + def interrupt_captured(self): + return self._read(_MCP_INTCAP) + + @property + def gpio(self): + return self._read(_MCP_GPIO) + @gpio.setter + def gpio(self, val): + # writing to this register modifies the OLAT register for pins configured as output + self._write(_MCP_GPIO, val) + + @property + def output_latch(self): + ''' + 输出锁存器 + ''' + return self._read(_MCP_OLAT) + @output_latch.setter + def output_latch(self, val): + # modifies the output latches on pins configured as outputs + self._write(_MCP_OLAT, val) + + +class Mcp23017(): + def __init__(self, i2c, address=0x20, bank=1): + self._i2c = i2c + self._address = address + self._config = 0x00 + self._virtual_pins = {} + if self._i2c.write(self._address, bytearray([0x05]), 1, bytearray([0]), 1) == -1: + raise OSError('MCP23017 not found at I2C address {0}'.format(self._address)) + + if bank == 1: + #往IOCON.bank写入bank,如果没找到i2c从设备地址 + self._i2c.write(self._address, bytearray([_MCP_IOCON_DEFAULT]), 1, bytearray([_MCP_IOCON_BANK]), 1) + self.init(bank) + + def init(self,bank): + + self.porta = Port(0, self) + self.portb = Port(1, self) + + self.io_config = 0x00 # io expander configuration - same on both ports, only need to write once + + # Reset to all inputs with no pull-ups and no inverted polarity. + self.porta.mode = 0xFF # in/out direction (0=out, 1=in) + self.portb.mode = 0xFF + self.porta.input_polarity = 0x00 # 反转端口输入极性 (0=normal, 1=invert) + self.portb.input_polarity = 0x00 + self.porta.interrupt_enable = 0x00 # int on change pins (0=disabled, 1=enabled) + self.portb.interrupt_enable = 0x00 + self.porta.default_value = 0x00 # default value for int on change + self.portb.default_value = 0x00 + self.porta.interrupt_compare_default = 0x00 # int on change control (0=compare to prev val, 1=compare to def val) + self.portb.interrupt_compare_default = 0x00 + self.pullup = 0x0000 # gpio weak pull up resistor - when configured as input (0=disabled, 1=enabled) + self.gpio = 0x0000 # port (0=logic low, 1=logic high) + + print(self.porta.mode,self.portb.mode) #0xFF + print(self.porta.interrupt_enable,self.portb.interrupt_enable) #0x00 + print(self.porta.gpio,self.portb.gpio) #0x00 + + def config(self, interrupt_polarity=None, interrupt_open_drain=None, sda_slew=None, sequential_operation=None, interrupt_mirror=None, bank=None): + io_config = self.porta.io_config + + if interrupt_polarity is not None: + # 将INT配置为push-pull + # 0: 低电平有效 + # 1: 高电平有效 + io_config = self._flip_bit(io_config, interrupt_polarity, _MCP_IOCON_INTPOL) + if interrupt_polarity: + # 如果设置为1,则取消ODR位 - interrupt_open_drain + interrupt_open_drain = False + if interrupt_open_drain is not None: + # configure INT as open drain, overriding interrupt_polarity + # 0: INTPOL sets the polarity + # 1: Open drain, INTPOL ignored + io_config = self._flip_bit(io_config, interrupt_open_drain, _MCP_IOCON_ODR) + if sda_slew is not None: + # 0: SDA引脚上的回转率功能已启用 + # 1: SDA引脚上的回转率功能已关闭 + io_config = self._flip_bit(io_config, sda_slew, _MCP_IOCON_DISSLW) + if sequential_operation is not None: + # 0: 启用,地址指针增量 + # 1: 禁用,地址指针已修复 + io_config = self._flip_bit(io_config, sequential_operation, _MCP_IOCON_SEQOP) + if interrupt_mirror is not None: + # 0: Independent INTA,INTB pins + # 1: Internally linked INTA,INTB pins + io_config = self._flip_bit(io_config, interrupt_mirror, _MCP_IOCON_MIRROR) + if bank is not None: + # 0: 寄存器在A和B端口之间交替 + # 1: 首先注册所有端口A,然后注册所有端口B + io_config = self._flip_bit(io_config, bank, _MCP_IOCON_BANK) + + # both ports share the same register, so you only need to write on one + self.porta.io_config = io_config + self._config = io_config + + def _flip_bit(self, value, condition, bit): + if condition: + value |= bit + else: + value &= ~bit + return value + + def pin(self, pin, mode=None, value=None, pullup=None, polarity=None, interrupt_enable=None, interrupt_compare_default=None, default_value=None): + assert 0 <= pin <= 15 + port = self.portb if pin // 8 else self.porta + bit = (1 << (pin % 8)) + if mode is not None: + # 0: Pin is configured as an output + # 1: Pin is configured as an input + port._flip_property_bit('mode', mode & 1, bit) + if value is not None: + # 0: 引脚设置为逻辑低 + # 1: 引脚设置为逻辑高 + port._flip_property_bit('gpio', value & 1, bit) + if pullup is not None: + # 0: 弱上拉100k欧姆电阻器禁用 + # 1: 弱上拉100k欧姆电阻器启用 + port._flip_property_bit('pullup', pullup & 1, bit) + if polarity is not None: + # 0: GPIO寄存器位反映输入引脚的相同逻辑状态 + # 1: GPIO寄存器位反映输入引脚的相反逻辑状态 + port._flip_property_bit('input_polarity', polarity & 1, bit) + if interrupt_enable is not None: + # 0: Disables GPIO input pin for interrupt-on-change event + # 1: Enables GPIO input pin for interrupt-on-change event + port._flip_property_bit('interrupt_enable', interrupt_enable & 1, bit) + if interrupt_compare_default is not None: + # 0: Pin value is compared against the previous pin value + # 1: Pin value is compared against the associated bit in the DEFVAL register + port._flip_property_bit('interrupt_compare_default', interrupt_compare_default & 1, bit) + if default_value is not None: + # 0: Default value for comparison in interrupt, when configured to compare against DEFVAL register + # 1: Default value for comparison in interrupt, when configured to compare against DEFVAL register + port._flip_property_bit('default_value', default_value & 1, bit) + if value is None: + return port.gpio & bit == bit + + def interrupt_triggered_gpio(self, port): + # 哪个gpio触发了中断 + # only 1 bit will be set + port = self.portb if port else self.porta + return port.interrupt_flag + + def interrupt_captured_gpio(self, port): + # 中断时捕获的gpio值 + # 读取此信息将清除当前中断 + port = self.portb if port else self.porta + return port.interrupt_captured + + # mode (IODIR register) + @property + def mode(self): + return self.porta.mode | (self.portb.mode << 8) + @mode.setter + def mode(self, val): + self.porta.mode = val + self.portb.mode = (val >> 8) + + # input_polarity (IPOL register) + @property + def input_polarity(self): + return self.porta.input_polarity | (self.portb.input_polarity << 8) + @input_polarity.setter + def input_polarity(self, val): + self.porta.input_polarity = val + self.portb.input_polarity = (val >> 8) + + # interrupt_enable (GPINTEN register) + @property + def interrupt_enable(self): + return self.porta.interrupt_enable | (self.portb.interrupt_enable << 8) + @interrupt_enable.setter + def interrupt_enable(self, val): + self.porta.interrupt_enable = val + self.portb.interrupt_enable = (val >> 8) + + # default_value (DEFVAL register) + @property + def default_value(self): + return self.porta.default_value | (self.portb.default_value << 8) + @default_value.setter + def default_value(self, val): + self.porta.default_value = val + self.portb.default_value = (val >> 8) + + # interrupt_compare_default (INTCON register) + @property + def interrupt_compare_default(self): + return self.porta.interrupt_compare_default | (self.portb.interrupt_compare_default << 8) + @interrupt_compare_default.setter + def interrupt_compare_default(self, val): + self.porta.interrupt_compare_default = val + self.portb.interrupt_compare_default = (val >> 8) + + # io_config (IOCON register) + # This register is duplicated in each port. Changing one changes both. + @property + def io_config(self): + return self.porta.io_config + @io_config.setter + def io_config(self, val): + self.porta.io_config = val + + # pullup (GPPU register) + @property + def pullup(self): + return self.porta.pullup | (self.portb.pullup << 8) + @pullup.setter + def pullup(self, val): + self.porta.pullup = val + self.portb.pullup = (val >> 8) + + # interrupt_flag (INTF register) + # read only + @property + def interrupt_flag(self): + return self.porta.interrupt_flag | (self.portb.interrupt_flag << 8) + + # interrupt_captured (INTCAP register) + # read only + @property + def interrupt_captured(self): + return self.porta.interrupt_captured | (self.portb.interrupt_captured << 8) + + # gpio (GPIO register) + @property + def gpio(self): + return self.porta.gpio | (self.portb.gpio << 8) + @gpio.setter + def gpio(self, val): + self.porta.gpio = val + self.portb.gpio = (val >> 8) + + # output_latch (OLAT register) + @property + def output_latch(self): + return self.porta.output_latch | (self.portb.output_latch << 8) + @output_latch.setter + def output_latch(self, val): + self.porta.output_latch = val + self.portb.output_latch = (val >> 8) + + # list interface + # mcp[pin] lazy creates a VirtualPin(pin, port) + def __getitem__(self, pin): + assert 0 <= pin <= 15 + if not pin in self._virtual_pins: + self._virtual_pins[pin] = VirtualPin(pin, self.portb if pin // 8 else self.porta) + return self._virtual_pins[pin] + +class VirtualPin(): + def __init__(self, pin, port): + self._pin = pin % 8 + self._bit = 1 << self._pin + self._port = port + + def _flip_bit(self, value, condition): + return value | self._bit if condition else value & ~self._bit + + def _get_bit(self, value): + return (value & self._bit) >> self._pin + + def value(self, val=None): + # if val, write, else read + if val is not None: + self._port.gpio = self._flip_bit(self._port.gpio, val & 1) + else: + return self._get_bit(self._port.gpio) + + def input(self, pull=None): + # if pull, enable pull up, else read + self._port.mode = self._flip_bit(self._port.mode, 1) # mode = input + if pull is not None: + self._port.pullup = self._flip_bit(self._port.pullup, pull & 1) # toggle pull up + + def output(self, val=None): + # if val, write, else read + self._port.mode = self._flip_bit(self._port.mode, 0) # mode = output + if val is not None: + self._port.gpio = self._flip_bit(self._port.gpio, val & 1) \ No newline at end of file diff --git a/libraries/MCP23017/mcp_test.py b/libraries/MCP23017/mcp_test.py new file mode 100644 index 0000000..16dfc25 --- /dev/null +++ b/libraries/MCP23017/mcp_test.py @@ -0,0 +1,53 @@ +from machine import I2C +from usr import mcp23017 +import utime + +if __name__=="__main__": + print("begin... ") + + i2c = I2C(I2C.I2C1, I2C.STANDARD_MODE) + mcp = mcp23017.Mcp23017(i2c, address=0x20) + mcp.pin(0, mode=1) + mcp.pin(1, mode=1, pullup=True) + mcp.pin(1) + mcp.pin(2, mode=0, value=1) + mcp.pin(3, mode=0, value=0) + + ''' + mcp.mode = 0x0000 + for n in range(100): + if n % 2 == 0: + #for i in range(15): + mcp.gpio = 0x0000 + else: + mcp.gpio = 0xFFFF + utime.sleep_ms(100) + + # list interface + #mcp[0].input() + #mcp[1].input(pull=1) + #mcp[1].value() + mcp[i].output(0) + utime.sleep_ms(10) + mcp[i].output(1) + utime.sleep_ms(10) + + # method interface + mcp.pin(0, mode=1) + mcp.pin(1, mode=1, pullup=True) + mcp.pin(1) + mcp.pin(2, mode=0, value=1) + mcp.pin(3, mode=0, value=0) + + mcp.config(interrupt_polarity=0, interrupt_mirror=1) + + # property interface 16-bit + mcp.mode = 0xfffe + mcp.gpio = 0x0001 + + # property interface 8-bit + mcp.porta.mode = 0xfe + mcp.portb.mode = 0xff + mcp.porta.gpio = 0x01 + mcp.portb.gpio = 0x02 + ''' \ No newline at end of file diff --git a/libraries/MCP2515/MCP2515.PDF b/libraries/MCP2515/MCP2515.PDF new file mode 100644 index 0000000..f268f4a Binary files /dev/null and b/libraries/MCP2515/MCP2515.PDF differ diff --git a/libraries/MCP2515/mcp2515_test.py b/libraries/MCP2515/mcp2515_test.py new file mode 100644 index 0000000..e6ae123 --- /dev/null +++ b/libraries/MCP2515/mcp2515_test.py @@ -0,0 +1,35 @@ +import MCP2515 +import utime +import _thread +from machine import Pin + +mcp2515 = MCP2515(0, Pin.GPIO21, 500, 512) +can_frame_cnt = 0 + + +def read_can_frame_thread(): + while True: + frame_num = mcp2515.get_frame_number() + if frame_num > 0: + can_data = mcp2515.read(frame_num) + global can_frame_cnt + can_frame_cnt = can_frame_cnt + frame_num + print("can_frame_cnt: {}".format(can_frame_cnt)) + utime.sleep_ms(100) + + +if __name__ == "__main__": + _thread.start_new_thread(read_can_frame_thread, ()) + send_cnt = 0 + while True: + if send_cnt < 1000: + send_bytearr = bytearray(2) + send_bytearr[1] = send_cnt & 0xff + send_bytearr[0] = (send_cnt>>8) & 0xff + mcp2515.write(0x6FF, 0, 0, bytes(send_bytearr)) + utime.sleep_ms(500) + send_cnt = send_cnt +1 + else: + print("send finish,cnt:", send_cnt) + break + \ No newline at end of file diff --git "a/libraries/PL51NF001/PL51NF001(NFC\346\270\251\345\272\246\346\240\207\347\255\276).pdf" "b/libraries/PL51NF001/PL51NF001(NFC\346\270\251\345\272\246\346\240\207\347\255\276).pdf" new file mode 100644 index 0000000..42a312b Binary files /dev/null and "b/libraries/PL51NF001/PL51NF001(NFC\346\270\251\345\272\246\346\240\207\347\255\276).pdf" differ diff --git a/libraries/PL51NF001/PL51NF001.py b/libraries/PL51NF001/PL51NF001.py new file mode 100644 index 0000000..9bc93c1 --- /dev/null +++ b/libraries/PL51NF001/PL51NF001.py @@ -0,0 +1,137 @@ +from machine import Pin +import utime + +''' +from machine import I2C + +I2C_SLAVE_ADDR = 0x000 +data = bytearray([0x0, 0x0]) +i2c_obj = I2C(I2C.I2C0, I2C.STANDARD_MODE) +i2c_obj.read(I2C_SLAVE_ADDR, bytearray([0x0, 0x0]), 1, data, 2, 0) +print(data) +''' + +class PL5NF001(object): + + def __init__(self): + self.CLK = Pin(Pin.GPIO9, Pin.OUT, Pin.PULL_PU, 1) # PL5NF001 CLK + self.DIO = Pin(Pin.GPIO8, Pin.OUT, Pin.PULL_PU, 1) # PL5NF001 DIO + + def delay_ms(self, ms): + utime.sleep_ms(ms) + + def delay_us(self, num): + # for i in range(num): + # pass + pass + + def start_signal(self): + self.CLK.write(1) + self.DIO.write(1) + self.delay_us(2) + self.DIO.write(0) + self.delay_us(2) + self.CLK.write(0) + self.delay_us(2) + + def stop_signal(self): + self.CLK.write(0) + self.DIO.write(0) + self.delay_us(2) + self.CLK.write(1) + self.delay_us(2) + self.DIO.write(1) + self.delay_us(2) + + def ack(self): + self.CLK.write(0) + self.DIO.write(0) + self.delay_us(2) + self.CLK.write(1) + self.delay_us(4) + self.CLK.write(0) + + def nack(self): + self.CLK.write(0) + self.DIO.write(1) + self.delay_us(2) + self.CLK.write(1) + self.delay_us(4) + self.CLK.write(0) + + def wait_ack(self): + self.DIO.setDirection(1) + # self.DIO = Pin(Pin.GPIO9, Pin.IN, Pin.PULL_PU, 1) + i = 0 + # self.delay_us(2) + self.CLK.write(1) + # self.delay_us(2) + while (self.DIO.read()): + i += 1 + if i > 2000: + self.stop_signal() + print('iic stop') + return 1 + self.CLK.write(0) + self.DIO.setDirection(0) + # self.DIO = Pin(Pin.GPIO9, Pin.OUT, Pin.PULL_DISABLE, 1) + return 0 + + def write_data(self, data): + j = 0 + self.CLK.write(0) + for j in range(8): + if data & 0x80: + self.DIO.write(1) + else: + self.DIO.write(0) + data <<= 1 + self.CLK.write(1) + self.delay_us(2) + self.CLK.write(0) + self.delay_us(2) + + def read_byte(self, ack): + self.DIO.setDirection(1) + # self.DIO = Pin(Pin.GPIO9, Pin.IN, Pin.PULL_DISABLE, 1) + recive = 0 + l = list() + utime.sleep_ms(12) + for i in range(0, 8): + self.CLK.write(0) + self.delay_us(2) + self.CLK.write(1) + self.delay_us(2) + recive << 1 + level = self.DIO.read() + l.append(level) + if level == 1: + recive | 1 + self.delay_us(2) + if ack == 1: + self.ack() + else: + self.nack() + print('ReadByte Recive = {}'.format(recive)) + # print(l) + self.DIO.setDirection(0) + return recive + + +if __name__ == '__main__': + # parse + p = PL5NF001() + p.start_signal() + p.write_data(0x00) + p.wait_ack() + p.write_data(0x01) + p.wait_ack() + for i in range(81): + p.read_byte(1) + p.read_byte(0) + # # p.read_byte(0) + # # p.read_byte(1) + # # p.read_byte(1) + p.stop_signal() + + diff --git a/libraries/QMA7981/QST-QMA7981.pdf b/libraries/QMA7981/QST-QMA7981.pdf new file mode 100644 index 0000000..0111549 Binary files /dev/null and b/libraries/QMA7981/QST-QMA7981.pdf differ diff --git a/libraries/QMA7981/qma7981.py b/libraries/QMA7981/qma7981.py new file mode 100644 index 0000000..f05d2aa --- /dev/null +++ b/libraries/QMA7981/qma7981.py @@ -0,0 +1,442 @@ +''' +File: i2c_qma7981.py +Project: i2c +File Created: Sunday, 11th March 2022 3:51:22 pm +Author: elian.wang + +----- +Copyright 2022 - 2022 quectel +''' + + +from machine import I2C +from machine import ExtInt +from machine import Pin +#from machine import I2C_simulation +import utime as time + +# TODO:AD0脚LSB of I2C address, or SDO of 4WSPI 当AD0接地时 IIC从机地址为0x12,当AD0接到VDDIO时从机地址为0x13; +# TODO:IIC支持快速和标准模式,100kHz到400kHz + + +class qma7981(): + i2c_log = None + i2c_dev = None + i2c_addre = 0x12 + step = None + acc = [0, 0, 0] + + # 中断类型 + SIG_MOT_INT = 0 + ANY_MOT_INT_X = 1 + ANY_MOT_INT_Y = 2 + ANY_MOT_INT_Z = 3 + NO_MOT_INT = 4 + HAND_RAISE_INT = 5 + HAND_DOWN_INT = 6 + STEP_INT = 7 + + IRQ_RISING = 0 + IRQ_FALLING = 1 + + PM_ADDR = 0x11 + STEP_CFG_ADDR = 0x12 + STEP_CLR_ADDR = 0x13 + # X轴加速度 + ACC_X_L_ADDR = 0x01 + ACC_X_H_ADDR = 0x02 + # Y轴加速度 + ACC_Y_L_ADDR = 0x03 + ACC_Y_H_ADDR = 0x04 + # Z轴加速度 + ACC_Z_L_ADDR = 0x05 + ACC_Z_H_ADDR = 0x06 + # step count + STEPCNT_L_ADDR = 0x07 + STEPCNT_M_ADDR = 0x08 + STEPCNT_H_ADDR = 0x0E + #获取触发any mot中断的动作方向 + INT_ST0_ADDR = 0x09 + # 加速度计算单位设置 + FSR_REG_ADDR = 0x0F + + STEP_SAMPLE_CNT_ADDR = 0x12 + STEP_PRECISION_ADDR = 0x13 + STEP_TIME_LOW_ADDR = 0x14 + STEP_TIME_UP_ADDR = 0x15 + # 中断使能 + INT_EN0_ADDR = 0x16 + INT_EN1_ADDR = 0x17 + INT_EN2_ADDR = 0x18 + # 中断map + INT_MAP0_ADDR = 0x19 + INT_MAP1_ADDR = 0x1A + INT_MAP2_ADDR = 0x1B + INT_MAP3_ADDR = 0x1C + # 中断引脚配置 + INTPIN_CONF_ADDR = 0x20 + INT_CFG_ADDR = 0x21 + + RAISE_WAKE_ADDR = 0x2A + DOWN_WAKE_ADDR = 0x2B + MOT_CONF0_ADDR = 0x2C + NO_MOT_TH_ADDR = 0x2D + # 任意方向震动中断触发值寄存器 + ANY_MOT_TH_ADDR = 0x2E + SIG_MOT_CONF_ADDR = 0x2F + RAISE_WAKE_PERIOD_ADDR = 0x35 + + + def _write(self, reg_addr, data): + self.i2c_dev.write(self.i2c_addre, + bytearray(reg_addr), 1, + bytearray(data), len(data)) + + def _read(self, reg_addr, length): + r_data = [0x00 for i in range(length)] + r_data = bytearray(r_data) + ret = self.i2c_dev.read(self.i2c_addre, + bytearray(reg_addr), 1, + r_data, length, + 0) + if ret == -1: + return [] + else: + return list(r_data) + + def __init__(self, user_cb, INT1=None, INT2=None, INT1_output_mode=1, INT2_output_mode=1): + self.cb = user_cb + self.i2c_dev = I2C(I2C.I2C0, I2C.FAST_MODE) # 返回i2c对象 + self.event = None + self.data = None + self.gpio_set_state = 0 # gpio设置的状态,用于分配中断对应引脚 + # set device into active mode + self._write([self.PM_ADDR], [0xC0]) + if INT1 != None: + if INT1_output_mode == 0: + self.extint = ExtInt(INT1, ExtInt.IRQ_RISING, ExtInt.PULL_PD, self.ext_cb) + data = self._read([self.INTPIN_CONF_ADDR], 1) + data[0] |= 0x01 + print('INTPIN_CONF_ADDR: {}'.format(data)) + self._write([self.INTPIN_CONF_ADDR], [data[0]]) + elif INT1_output_mode == 1: + self.extint = ExtInt(INT1, ExtInt.IRQ_FALLING, ExtInt.PULL_PU, self.ext_cb) + data = self._read([self.INTPIN_CONF_ADDR], 1) + data[0] &= 0xFE + print('INTPIN_CONF_ADDR: {}'.format(data)) + self._write([self.INTPIN_CONF_ADDR], [data[0]]) + else: + raise Exception('set gpio1 trigger mode fault') + self.extint.enable() + if INT2 != None: + if INT2_output_mode == 0: + self.extint = ExtInt(INT2, ExtInt.IRQ_RISING , ExtInt.PULL_PD , self.ext_cb) + data = self._read([self.INTPIN_CONF_ADDR], 1) + data[0] |= 0x04 + print('INTPIN_CONF_ADDR: {}'.format(data)) + self._write([self.INTPIN_CONF_ADDR], [data[0]]) + elif INT2_output_mode == 1: + data = self._read([self.INTPIN_CONF_ADDR], 1) + data[0] &= 0xFB + print('INTPIN_CONF_ADDR: {}'.format(data)) + self._write([self.INTPIN_CONF_ADDR], [data[0]]) + self.extint = ExtInt(INT2, ExtInt.IRQ_FALLING, ExtInt.PULL_PU, self.ext_cb) + else: + raise Exception('set gpio2 trigger mode fault') + self.extint.enable() + if INT1 != None and INT2 != None: + self.gpio_set_state = 3 + elif INT1 != None: + self.gpio_set_state = 1 + elif INT2 != None: + self.gpio_set_state = 2 + + self._write([self.FSR_REG_ADDR], [0xF8]) + # interrupt is in latch mode + self._write([self.INT_CFG_ADDR], [0x1F]) + time.sleep_ms(10) + + def ext_cb(self, args): + data = self._read([self.INT_ST0_ADDR], 3) + direction = data[0] & 0x08 + print('state {}'.format(data)) + if data[1] & 0x01: + self.event = self.SIG_MOT_INT # significant interrupt is active + elif data[0] & 0x01: + self.event = self.ANY_MOT_INT_X # any_motion interrupt is triggered by X + elif data[0] & 0x02: + self.event = self.ANY_MOT_INT_Y # any_motion interrupt is triggered by Y + elif data[0] & 0x04: + self.event = self.ANY_MOT_INT_Z # any_motion interrupt is triggered by Z + elif data[0] & 0x80: + self.event = self.NO_MOT_INT # no_motion interrupt is triggered + elif data[1] & 0x02: + self.event = self.HAND_RAISE_INT # raise hand interrupt is active + elif data[1] & 0x04: + self.event = self.HAND_DOWN_INT # hand down interrupt is active + elif data[1] & 0x08: + self.event = self.STEP_INT # step interrupt is active + if data[0] & 0x07 or data[1] & 0x01: + self.data = self.readacc() + print('acc {}'.format(self.data)) + elif data[1] & 0x48: + self.data = self.readstep() + print('step {}'.format(self.readstep)) + self.cb(self.event, self.data) + + def set_any_motion_intr(self, en, threshod=0, sample_times=1): + if en == True: + # set any motion interrupt consecutive times + data = self._read([self.MOT_CONF0_ADDR], 1) + data[0] &= 0xFC + if sample_times <= 3: + data[0] |= sample_times + else: + data[0] |= 0x01 # 2 times + self._write([self.MOT_CONF0_ADDR], [data[0]]) + # set the full of accelerometer 0xF8==>Acceleration range:16g; Resolution:1.95mg/LSB + self._write([self.FSR_REG_ADDR], [0xF8]) + # set any motion interrupt threshod value + threshod = threshod // 31 # 1.95mg * 16 + print('threshod{}'.format(threshod)) + self._write([self.ANY_MOT_TH_ADDR], [threshod]) # 16 / bits + self._write([self.SIG_MOT_CONF_ADDR], [0x00]) + # 使能中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] |= 0x07 + print('intr_en{}'.format(intr_en)) + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + # 设置中断脚 + if self.gpio_set_state & 0x01: + intr_map = self._read([self.INT_MAP1_ADDR], 1) + intr_map[0] |= 0x01 + print('intr_map{}'.format(intr_map)) + self._write([self.INT_MAP1_ADDR], [intr_map[0]]) + elif self.gpio_set_state & 0x02: + intr_map = self._read([self.INT_MAP3_ADDR], 1) + intr_map[0] |= 0x01 + self._write([self.INT_MAP3_ADDR], [intr_map[0]]) + else: + # 取消中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] &= 0xF8 + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + + def set_sig_motion_intr(self, en, threshod=0, sample_times=1, axis_direction=0): + if en == True: + # set any motion interrupt consecutive times + data = self._read([self.MOT_CONF0_ADDR], 1) + data[0] &= 0xFC + if sample_times <= 3: + data[0] |= sample_times + else: + data[0] |= 0x01 # 2 times + self._write([self.MOT_CONF0_ADDR], [data[0]]) + # set the full of accelerometer 0xF8==>Acceleration range:16g; Resolution:1.95mg/LSB + self._write([self.FSR_REG_ADDR], [0xF8]) + # set any motion interrupt threshod value + threshod = threshod // 31 # 1.95mg * 16 + self._write([self.ANY_MOT_TH_ADDR], [threshod]) # 16 / bits + self._write([self.SIG_MOT_CONF_ADDR], [0x01]) + # 使能中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] &= 0xF8 + if axis_direction == 0: + intr_en[0] |= 0x01 + elif axis_direction == 1: + intr_en[0] |= 0x02 + elif axis_direction == 2: + intr_en[0] |= 0x04 + print('intr_en{}'.format(intr_en)) + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + # 设置中断脚 + if self.gpio_set_state & 0x01: + intr_map = self._read([self.INT_MAP0_ADDR], 1) + intr_map[0] |= 0x01 + self._write([self.INT_MAP0_ADDR], [intr_map[0]]) + elif self.gpio_set_state & 0x02: + intr_map = self._read([self.INT_MAP2_ADDR], 1) + intr_map[0] |= 0x01 + self._write([self.INT_MAP2_ADDR], [intr_map[0]]) + else: + # 取消中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] &= 0xF8 + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + + def set_no_motion_intr(self, en, threshod, duration_time = 10, axis_direction=0x03): + if en == True: + # set no motion interrupt consecutive times + data = self._read([self.MOT_CONF0_ADDR], 1) + data[0] &= 0x03 + data[0] |= (duration_time << 2) + print('MOT_CONF0_ADDR:{}'.format(data)) + self._write([self.MOT_CONF0_ADDR], [data[0]]) + # set no motion interrupt threshod value + threshod = threshod // 31 # 1.95mg * 16 + self._write([self.NO_MOT_TH_ADDR], [threshod]) # 16 / bits + self._write([self.SIG_MOT_CONF_ADDR], [0x01]) + # 使能中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] &= 0x1F + if axis_direction & 0x01: + intr_en[0] |= 0x20 + if axis_direction & 0x02: + intr_en[0] |= 0x40 + if axis_direction & 0x04: + intr_en[0] |= 0x80 + print('INT_EN2_ADDR:{}'.format(intr_en)) + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + # 设置中断脚 + if self.gpio_set_state & 0x01: + intr_map = self._read([self.INT_MAP1_ADDR], 1) + intr_map[0] |= 0x80 + self._write([self.INT_MAP1_ADDR], [intr_map[0]]) + elif self.gpio_set_state & 0x02: + intr_map = self._read([self.INT_MAP3_ADDR], 1) + intr_map[0] |= 0x80 + self._write([self.INT_MAP3_ADDR], [intr_map[0]]) + else: + # 取消中断 + intr_en = self._read([self.INT_EN2_ADDR], 1) + intr_en[0] &= 0x1F + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + + + def set_step_intr(self, intr_type, en, threshod=0, axis_direction = 0): + if en == True: + # enable step counter + self._write([self.STEP_CFG_ADDR], [0x8C]) + # 使能中断 + intr_en = self._read([self.INT_EN0_ADDR], 1) + intr_en[0] |= 0x08 + print('intr_en{}'.format(intr_en)) + self._write([self.INT_EN0_ADDR], [intr_en[0]]) + # 设置中断脚 + if self.gpio_set_state & 0x02: + intr_map = self._read([self.INT_MAP2_ADDR], 1) + intr_map[0] |= 0x08 + print('intr_map{}'.format(intr_map)) + self._write([self.INT_MAP2_ADDR], [intr_map[0]]) + elif self.gpio_set_state & 0x01: + intr_map = self._read([self.INT_MAP0_ADDR], 1) + intr_map[0] |= 0x08 + print('intr_map{}'.format(intr_map)) + self._write([self.INT_MAP0_ADDR], [intr_map[0]]) + else: + # 取消中断 + intr_en = self._read([self.INT_EN0_ADDR], 1) + intr_en[0] &= 0xF7 + self._write([self.INT_EN2_ADDR], [intr_en[0]]) + + def set_raise_intr(self, en, wake_sum_th=10, wake_diff_th=1.0): + if en: + if wake_sum_th and wake_diff_th!=0 and wake_diff_th < 1.2: + wake_sum_th = int(wake_sum_th * 2) + wake_diff_th = int((wake_diff_th - 0.2)*10) + data = (wake_sum_th & 0x3F) | ((wake_diff_th & 0x03)<<6) + print('RAISE_WAKE_ADDR:{}'.format(data)) + self._write([self.RAISE_WAKE_ADDR], [data]) + + data = wake_diff_th >> 2 + read_data = self._read([self.DOWN_WAKE_ADDR], 1) + data = (read_data[0] & 0xFC) | data + print('DOWN_WAKE_ADDR:{}'.format(data)) + self._write([self.DOWN_WAKE_ADDR], [data]) + + # 使能中断 + intr_en = self._read([self.INT_EN0_ADDR], 1) + intr_en[0] |= 0x02 + print('intr_en{}'.format(intr_en)) + self._write([self.INT_EN0_ADDR], [intr_en[0]]) + + # 设置中断脚 + if self.gpio_set_state & 0x02: + intr_map = self._read([self.INT_MAP2_ADDR], 1) + intr_map[0] |= 0x02 + print('intr_map INT_MAP2_ADDR:{}'.format(intr_map)) + self._write([self.INT_MAP2_ADDR], [intr_map[0]]) + elif self.gpio_set_state & 0x01: + intr_map = self._read([self.INT_MAP0_ADDR], 1) + intr_map[0] |= 0x02 + print('intr_map INT_MAP0_ADDR:{}'.format(intr_map)) + self._write([self.INT_MAP0_ADDR], [intr_map[0]]) + else: + intr_en = self._read([self.INT_EN0_ADDR], 1) + intr_en[0] &= 0xFD + print('intr_en{}'.format(intr_en)) + self._write([self.INT_EN0_ADDR], [intr_en[0]]) + + def readstep(self): + data0 = self._read([self.STEPCNT_L_ADDR], 1) + data1 = self._read([self.STEPCNT_M_ADDR], 1) + data2 = self._read([self.STEPCNT_H_ADDR], 1) + if data0[0] != -1 and data1[0] != -1 and data2[0] != -1: + self.step = (data2[0] << 8) | (data1[0] << 8) | data0[0] + return self.step + + def readacc(self): + data = self._read([self.ACC_X_L_ADDR], 6) + print('acc data{}'.format(data)) + + if len(data) != 0: + if data[1] & 0x80: + self.acc[0] = (0x4000 - ((data[0]|(data[1]<<8)) >> 2)) * -1.95 + else: + self.acc[0] = ((data[0]|(data[1]<<8)) >> 2) * 1.95 # 根据数据QMA7981_FSR_REG寄存器计算 + if data[3] & 0x80: + self.acc[1] = (0x4000 - ((data[2]|(data[3]<<8)) >> 2)) * -1.95 + else: + self.acc[1] = ((data[2]|(data[3]<<8)) >> 2) * 1.95 # 根据数据QMA7981_FSR_REG寄存器计算 + if data[5] & 0x80: + self.acc[2] = (0x4000 - ((data[4]|(data[5]<<8)) >> 2)) * -1.95 + else: + self.acc[2] = ((data[4]|(data[5]<<8)) >> 2) * 1.95 # 根据数据QMA7981_FSR_REG寄存器计算 + print('acc value{}'.format(self.acc)) + return self.acc + + def read_sta_reg(self): + data = qma7981_dev._read([qma7981_dev.INT_ST0_ADDR], 3) + print('INT_ST0:{}'.format(data)) + data = qma7981_dev._read([qma7981_dev.INT_EN0_ADDR], 3) + print('INT_EN0:{}'.format(data)) + data = qma7981_dev._read([qma7981_dev.INT_MAP0_ADDR], 4) + print('INT_MAP0:{}'.format(data)) + data = self._read([self.ACC_X_L_ADDR], 6) + print('acc data{}'.format(data)) + data = qma7981_dev._read([qma7981_dev.INTPIN_CONF_ADDR], 1) + print('INTPIN_CONF_ADDR:{}'.format(data)) + + def clearstep(self): + self._write([self.STEP_CLR_ADDR], [0xFF]) + + +qma7981_dev = None + +def user_cb_test(event, data): + if event == qma7981.SIG_MOT_INT: + print("significant interrupt is active") + elif event == qma7981.ANY_MOT_INT_X: + print("any_motion interrupt is triggered by X") + elif event == qma7981.ANY_MOT_INT_Y: + print("any_motion interrupt is triggered by Y") + elif event == qma7981.ANY_MOT_INT_Z: + print("any_motion interrupt is triggered by Z") + elif event == qma7981.NO_MOT_INT: + print("no_motion interrupt is triggered") + elif event == qma7981.HAND_RAISE_INT: + print("raise hand interrupt is active") + elif event == qma7981.HAND_DOWN_INT: + print("hand down interrupt is active") + elif event == qma7981.HAND_DOWN_INT: + print("hand down interrupt is active") + print('get value {}'.format(data)) + +if __name__ == "__main__": + print('start') + # GPIO7 GPIO33 + qma7981_dev = qma7981(user_cb_test, INT1=ExtInt.GPIO33, INT1_output_mode=qma7981.IRQ_FALLING) + qma7981_dev.set_any_motion_intr(True, threshod=200, sample_times=1) + for i in range(100): + qma7981_dev.readacc() + time.sleep(1) \ No newline at end of file diff --git a/libraries/RC522/MFRC522.PDF b/libraries/RC522/MFRC522.PDF new file mode 100644 index 0000000..da715e3 Binary files /dev/null and b/libraries/RC522/MFRC522.PDF differ diff --git a/libraries/RC522/mfrc522.py b/libraries/RC522/mfrc522.py new file mode 100644 index 0000000..d60a5cb --- /dev/null +++ b/libraries/RC522/mfrc522.py @@ -0,0 +1,596 @@ + +# import RPi.GPIO as GPIO +# import spidev +# import signal +# import time +# import logging +# https://github.com/pimylifeup/Mfrc522-python/blob/master/Mfrc522/Mfrc522.py + +from machine import Pin +from machine import SPI +import utime +from machine import ExtInt +import _thread + + +class Mfrc522(object): + ''' + RC522类 + 开放接口:write(text),read(),read_id(),Mfrc522_Read(blockAddr),Mfrc522_Write(blockAddr, writeData) + ''' + MAX_LEN = 16 + + PCD_IDLE = 0x00 #取消当前命令 + PCD_AUTHENT = 0x0E #验证密钥 + PCD_RECEIVE = 0x08 #接收数据 + PCD_TRANSMIT = 0x04 #发送消息 + PCD_TRANSCEIVE = 0x0C #发送并接收数据 + PCD_RESETPHASE = 0x0F #复位 + PCD_CALCCRC = 0x03 #CRC计算 + + PICC_REQIDL = 0x26 #寻天线区内未进入休眠状态的卡 + PICC_REQALL = 0x52 #寻天线区内全部卡 + PICC_ANTICOLL = 0x93 #防冲撞 + #修改点,之前93重复 + PICC_SElECTTAG = 0x95 #寻卡 + PICC_AUTHENT1A = 0x60 #验证A密钥 + PICC_AUTHENT1B = 0x61 #验证B密钥 + PICC_READ = 0x30 #读块 + PICC_WRITE = 0xA0 #写块 + PICC_DECREMENT = 0xC0 #扣款 + PICC_INCREMENT = 0xC1 #充值 + PICC_RESTORE = 0xC2 #调块数据到缓冲区 + PICC_TRANSFER = 0xB0 #保存缓冲区数据 + PICC_HALT = 0x50 #休眠 + + MI_OK = 0 + MI_NOTAGERR = 1 + MI_ERR = 2 + + #寄存器 + Reserved00 = 0x00 + CommandReg = 0x01 + CommIEnReg = 0x02 + DivlEnReg = 0x03 + CommIrqReg = 0x04 + DivIrqReg = 0x05 + ErrorReg = 0x06 + Status1Reg = 0x07 + Status2Reg = 0x08 + FIFODataReg = 0x09 + FIFOLevelReg = 0x0A + WaterLevelReg = 0x0B + ControlReg = 0x0C + BitFramingReg = 0x0D + CollReg = 0x0E + Reserved01 = 0x0F + + Reserved10 = 0x10 + ModeReg = 0x11 + TxModeReg = 0x12 + RxModeReg = 0x13 + TxControlReg = 0x14 + TxAutoReg = 0x15 + TxSelReg = 0x16 + RxSelReg = 0x17 + RxThresholdReg = 0x18 + DemodReg = 0x19 + Reserved11 = 0x1A + Reserved12 = 0x1B + MifareReg = 0x1C + Reserved13 = 0x1D + Reserved14 = 0x1E + SerialSpeedReg = 0x1F + + Reserved20 = 0x20 + CRCResultRegM = 0x21 + CRCResultRegL = 0x22 + Reserved21 = 0x23 + ModWidthReg = 0x24 + Reserved22 = 0x25 + RFCfgReg = 0x26 + GsNReg = 0x27 + CWGsPReg = 0x28 + ModGsPReg = 0x29 + TModeReg = 0x2A + TPrescalerReg = 0x2B + TReloadRegH = 0x2C + TReloadRegL = 0x2D + TCounterValueRegH = 0x2E + TCounterValueRegL = 0x2F + + Reserved30 = 0x30 + TestSel1Reg = 0x31 + TestSel2Reg = 0x32 + TestPinEnReg = 0x33 + TestPinValueReg = 0x34 + TestBusReg = 0x35 + AutoTestReg = 0x36 + VersionReg = 0x37 + AnalogTestReg = 0x38 + TestDAC1Reg = 0x39 + TestDAC2Reg = 0x3A + TestADCReg = 0x3B + Reserved31 = 0x3C + Reserved32 = 0x3D + Reserved33 = 0x3E + Reserved34 = 0x3F + + serNum = [] + KEY = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] + BLOCK_ADDRS = [8, 9, 10] + + def __init__(self): + + self.Mfrc522_Init() + + + def _Mfrc522_Reset(self): + self._Write_Mfrc522(self.CommandReg, self.PCD_RESETPHASE) + + def _Write_Mfrc522(self, addr, val): + print("this bug write") + raise NotImplementedError + + def _Read_Mfrc522(self, addr): + print("this bug read") + raise NotImplementedError + + def _Close_Mfrc522(self): + raise NotImplementedError + + def _SetBitMask(self, reg, mask): + tmp = self._Read_Mfrc522(reg) + self._Write_Mfrc522(reg, tmp | mask) + + def _ClearBitMask(self, reg, mask): + ''' + 寄存器清位 + ''' + tmp = self._Read_Mfrc522(reg) + self._Write_Mfrc522(reg, tmp & (~mask)) + + def AntennaOn(self): + ''' + 开启天线 + ''' + temp = self._Read_Mfrc522(self.TxControlReg) + if (~(temp & 0x03)): + self._SetBitMask(self.TxControlReg, 0x03) + + def AntennaOff(self): + ''' + 关闭天线 + ''' + self._ClearBitMask(self.TxControlReg, 0x03) + + def _Mfrc522_ToCard(self, command, sendData): + backData = [] + backLen = 0 + status = self.MI_ERR + irqEn = 0x00 + waitIRq = 0x00 + if command == self.PCD_AUTHENT: + irqEn = 0x12 + waitIRq = 0x10 + if command == self.PCD_TRANSCEIVE: + irqEn = 0x77 + waitIRq = 0x30 + + self._Write_Mfrc522(self.CommIEnReg, irqEn | 0x80) + self._ClearBitMask(self.CommIrqReg, 0x80) + self._SetBitMask(self.FIFOLevelReg, 0x80) + + self._Write_Mfrc522(self.CommandReg, self.PCD_IDLE) + + for i in range(len(sendData)): + self._Write_Mfrc522(self.FIFODataReg, sendData[i]) + + self._Write_Mfrc522(self.CommandReg, command) + + if command == self.PCD_TRANSCEIVE: + self._SetBitMask(self.BitFramingReg, 0x80) + + i = 5 + while True: + n = self._Read_Mfrc522(self.CommIrqReg) + i -= 1 + if ~((i != 0) and ~(n & 0x01) and ~(n & waitIRq)): + break + + self._ClearBitMask(self.BitFramingReg, 0x80) + + if i != 0: + if (self._Read_Mfrc522(self.ErrorReg) & 0x1B) == 0x00: + status = self.MI_OK + if n & irqEn & 0x01: + status = self.MI_NOTAGERR + if command == self.PCD_TRANSCEIVE: + n = self._Read_Mfrc522(self.FIFOLevelReg) + lastBits = self._Read_Mfrc522(self.ControlReg) & 0x07 + if lastBits != 0: + backLen = (n - 1) * 8 + lastBits + else: + backLen = n * 8 + + if n == 0: + n = 1 + if n > self.MAX_LEN: + n = self.MAX_LEN + + for i in range(n): + backData.append(self._Read_Mfrc522(self.FIFODataReg)) + else: + status = self.MI_ERR + + return (status, backData, backLen) + + def _Mfrc522_Request(self, reqMode): + ''' + 寻卡 + ''' + TagType = [] + + self._Write_Mfrc522(self.BitFramingReg, 0x07) + + TagType.append(reqMode) + (status, backData, backBits) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, TagType) + + if ((status != self.MI_OK) | (backBits != 0x10)): + status = self.MI_ERR + + return (status, backBits) + + def _Mfrc522_Anticoll(self): + ''' + 防冲撞 + ''' + serNumCheck = 0 + + serNum = [] + + self._Write_Mfrc522(self.BitFramingReg, 0x00) + + serNum.append(self.PICC_ANTICOLL) + serNum.append(0x20) + + (status, backData, backBits) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, serNum) + + if (status == self.MI_OK): + i = 0 + if len(backData) == 5: + for i in range(4): + serNumCheck = serNumCheck ^ backData[i] + if serNumCheck != backData[4]: + status = self.MI_ERR + else: + status = self.MI_ERR + + return (status, backData) + + def _CalulateCRC(self, pIndata): + self._ClearBitMask(self.DivIrqReg, 0x04) + self._SetBitMask(self.FIFOLevelReg, 0x80) + + for i in range(len(pIndata)): + self._Write_Mfrc522(self.FIFODataReg, pIndata[i]) + + self._Write_Mfrc522(self.CommandReg, self.PCD_CALCCRC) + i = 0xFF + while True: + n = self._Read_Mfrc522(self.DivIrqReg) + i -= 1 + if not ((i != 0) and not (n & 0x04)): + break + pOutData = [] + pOutData.append(self._Read_Mfrc522(self.CRCResultRegL)) + pOutData.append(self._Read_Mfrc522(self.CRCResultRegM)) + return pOutData + + def _Mfrc522_SelectTag(self, serNum): + ''' + 选择卡片 + ''' + backData = [] + buf = [] + buf.append(self.PICC_SElECTTAG) + buf.append(0x70) + + for i in range(5): + buf.append(serNum[i]) + + pOut = self._CalulateCRC(buf) + buf.append(pOut[0]) + buf.append(pOut[1]) + (status, backData, backLen) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, buf) + + if (status == self.MI_OK) and (backLen == 0x18): + print("Size: " + str(backData[0])) + return backData[0] + else: + return 0 + + def Mfrc522_Auth(self, authMode, BlockAddr, Sectorkey, serNum): + ''' + 验证卡片密码 + ''' + buff = [] + + # First byte should be the authMode (A or B) + buff.append(authMode) + + # Second byte is the trailerBlock (usually 7) + buff.append(BlockAddr) + + # Now we need to append the authKey which usually is 6 bytes of 0xFF + for i in range(len(Sectorkey)): + buff.append(Sectorkey[i]) + + # Next we append the first 4 bytes of the UID + for i in range(4): + buff.append(serNum[i]) + + # Now we start the authentication itself + (status, backData, backLen) = self._Mfrc522_ToCard(self.PCD_AUTHENT, buff) + + # Check if an error occurred + if not (status == self.MI_OK): + print("AUTH ERROR!!") + if not (self._Read_Mfrc522(self.Status2Reg) & 0x08) != 0: + print("AUTH ERROR(status2reg & 0x08) != 0") + + # Return the status + return status + + def Mfrc522_StopCrypto1(self): + self._ClearBitMask(self.Status2Reg, 0x08) + + def Mfrc522_Read(self, blockAddr): + ''' + 读数据 + ''' + recvData = [] + recvData.append(self.PICC_READ) + recvData.append(blockAddr) + pOut = self._CalulateCRC(recvData) + recvData.append(pOut[0]) + recvData.append(pOut[1]) + (status, backData, backLen) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, recvData) + if not (status == self.MI_OK): + print("Error while reading!") + + if len(backData) == 16: + print("Sector " + str(blockAddr) + " " + str(backData)) + return backData + else: + return None + + def Mfrc522_Write(self, blockAddr, writeData): + ''' + 写数据到卡 + @param blockAddr: 块地址 + @param writeData: 写入的数据,16字节 + ''' + buff = [] + buff.append(self.PICC_WRITE) + buff.append(blockAddr) + crc = self._CalulateCRC(buff) + buff.append(crc[0]) + buff.append(crc[1]) + (status, backData, backLen) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, buff) + if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): + status = self.MI_ERR + + print("%s backdata &0x0F == 0x0A %s" % (backLen, backData[0] & 0x0F)) + if status == self.MI_OK: + buf = [] + for i in range(16): + buf.append(writeData[i]) + + crc = self._CalulateCRC(buf) + buf.append(crc[0]) + buf.append(crc[1]) + (status, backData, backLen) = self._Mfrc522_ToCard( + self.PCD_TRANSCEIVE, buf) + if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): + print("Error while writing") + if status == self.MI_OK: + print("Data written") + + def Mfrc522_DumpClassic1K(self, key, uid): + for i in range(64): + status = self.Mfrc522_Auth(self.PICC_AUTHENT1A, i, key, uid) + # Check if authenticated + if status == self.MI_OK: + self.Mfrc522_Read(i) + else: + print("Authentication error") + + def Mfrc522_Init(self): + self._Mfrc522_Reset() + + self._Write_Mfrc522(self.TModeReg, 0x8D) + self._Write_Mfrc522(self.TPrescalerReg, 0x3E) + self._Write_Mfrc522(self.TReloadRegL, 30) + self._Write_Mfrc522(self.TReloadRegH, 0) + + self._Write_Mfrc522(self.TxAutoReg, 0x40) + self._Write_Mfrc522(self.ModeReg, 0x3D) + self.AntennaOff() + self.AntennaOn() + self.M500PcdConfigISOType('A') + + def M500PcdConfigISOType(self, type): + + if type == 'A': + self._ClearBitMask(self.Status2Reg, 0x08) + self._Write_Mfrc522(self.ModeReg, 0x3D) + self._Write_Mfrc522(self.RxSelReg, 0x86) + self._Write_Mfrc522(self.RFCfgReg, 0x7F) + self._Write_Mfrc522(self.TReloadRegL, 30) + self._Write_Mfrc522(self.TReloadRegH, 0) + self._Write_Mfrc522(self.TModeReg, 0x8D) + self._Write_Mfrc522(self.TPrescalerReg, 0x3E) + utime.sleep_us(1000) + self.AntennaOn() + else: + return 1 + + def read(self): + id, text = self.read_no_block() + while not id: + id, text = self.read_no_block() + return id, text + + def read_id(self): + ''' + 读id + ''' + id = self.read_id_no_block() + while not id: + id = self.read_id_no_block() + return id + + def read_id_no_block(self): + (status, TagType) = self._Mfrc522_Request(self.PICC_REQIDL) + if status != self.MI_OK: + return None + (status, uid) = self._Mfrc522_Anticoll() + if status != self.MI_OK: + return None + print("uid=", uid) + return self._uid_to_num(uid) + + def read_no_block(self): + (status, TagType) = self._Mfrc522_Request(self.PICC_REQIDL) + if status != self.MI_OK: + return None, None + (status, uid) = self._Mfrc522_Anticoll() + if status != self.MI_OK: + return None, None + id = self._uid_to_num(uid) + self._Mfrc522_SelectTag(uid) + status = self.Mfrc522_Auth( + self.PICC_AUTHENT1A, 11, self.KEY, uid) + data = [] + text_read = '' + if status == self.MI_OK: + for block_num in self.BLOCK_ADDRS: + block = self.Mfrc522_Read(block_num) + if block: + data += block + if data: + text_read = ''.join(chr(i) for i in data) + self.Mfrc522_StopCrypto1() + return id, text_read + + def write(self, text): + id, text_in = self.write_no_block(text) + while not id: + id, text_in = self.write_no_block(text) + return id, text_in + + def write_no_block(self, text): + (status, TagType) = self._Mfrc522_Request(self.PICC_REQIDL) + if status != self.MI_OK: + print("cannot find the card!") + return None, None + (status, uid) = self._Mfrc522_Anticoll() + if status != self.MI_OK: + return None, None + id = self._uid_to_num(uid) + self._Mfrc522_SelectTag(uid) + status = self.Mfrc522_Auth( + self.PICC_AUTHENT1A, 11, self.KEY, uid) + self.Mfrc522_Read(11) + if status == self.MI_OK: + data = bytearray() + data.extend(bytearray(text.ljust( + len(self.BLOCK_ADDRS) * 16).encode('ascii'))) + i = 0 + for block_num in self.BLOCK_ADDRS: + self.Mfrc522_Write(block_num, data[(i*16):(i+1)*16]) + i += 1 + self.Mfrc522_StopCrypto1() + return id, text[0:(len(self.BLOCK_ADDRS) * 16)] + + def _uid_to_num(self, uid): + n = 0 + for i in range(0, 5): + n = n * 256 + uid[i] + return n + + def _irq_callback(self, para): + print("irq call:", para) + self.read_id_no_block() + + def _irq_set(self, pin_irq, irq_cb): + if pin_irq is None: + print("Interrupt pin is not set") + return + + regVal = 0 + # self._Write_Mfrc522(self.CommIEnReg, regVal) + self._Write_Mfrc522(self.CommIEnReg, regVal | 0x20) + self._Write_Mfrc522(self.DivlEnReg, 0x90) + + print("get enreg:",self._Read_Mfrc522(self.CommIEnReg)) + + if irq_cb is None: + self._irq_fun = self._irq_callback + else: + self._irq_fun = irq_cb + + print("p_irq = ",pin_irq) + self._irq = ExtInt(pin_irq, ExtInt.IRQ_FALLING, + ExtInt.PULL_PU, self._irq_fun) + + +class Mfrc522_spi(Mfrc522): + + def __init__(self, spi=None, *, spi_no=1, spi_mode=0, spi_clk=0, pin_rst, pin_irq=None, irq_cb=None): + if spi is None: + self._spi = SPI(spi_no, spi_mode, spi_clk) + else: + self._spi = spi + self._rst = Pin(pin_rst, Pin.OUT, Pin.PULL_DISABLE, 0) + utime.sleep(1) + self._rst.write(1) + if pin_irq != None: + self._irq_set(pin_irq, irq_cb) + + super().__init__() + + def _Write_Mfrc522(self, addr, val): + write_buf = bytearray([(addr << 1) & 0x7E, val]) + # print("write_buf:",write_buf) + self._spi.write(write_buf, len(write_buf)) + + def _Read_Mfrc522(self, addr): + write_buf = bytearray([((addr << 1) & 0x7E) | 0x80, 0]) + read_buf = bytearray(len(write_buf)) + self._spi.write_read(read_buf, write_buf, len(write_buf)) + # print("read_buf:",read_buf) + return read_buf[1] + + def _Close_Mfrc522(self): + pass + +def rc522_test(): + reader = Mfrc522_spi(pin_rst=Pin.GPIO12, pin_irq=Pin.GPIO11) + print("init finish.") + blockAddr = 0x01 + data = [0x00,0x0A,0x10,0x00,0x0C,0x00,0xA0,0x05,0x00,0x40,0x40,0x00,0x10,0x20] + reader.Mfrc522_Write(blockAddr,data) + read_data = reader.Mfrc522_Read(blockAddr) + #id = reader.read_id() + print('card id is {0}'.format(read_data)) + utime.sleep_ms(200) + +if __name__ == '__main__': + _thread.start_new_thread(rc522_test, ()) diff --git a/libraries/RDA5807/1810010217_RDA-Microelectronics-RDA5807M_C82537.pdf b/libraries/RDA5807/1810010217_RDA-Microelectronics-RDA5807M_C82537.pdf new file mode 100644 index 0000000..a4f239e Binary files /dev/null and b/libraries/RDA5807/1810010217_RDA-Microelectronics-RDA5807M_C82537.pdf differ diff --git a/libraries/RDA5807/rda5807.py b/libraries/RDA5807/rda5807.py new file mode 100644 index 0000000..e17c883 --- /dev/null +++ b/libraries/RDA5807/rda5807.py @@ -0,0 +1,320 @@ +from machine import Pin +import utime as time + +ACK = 0 +NACK = 1 + +rdaclk = Pin.GPIO2 +rdadio = Pin.GPIO3 + +RDA_WRITE = 0x22 +RDA_READ = 0x23 + +RDA_R00 = 0x00 +RDA_R02 = 0x02 +RDA_R03 = 0x03 +RDA_R04 = 0x04 +RDA_R05 = 0x05 +RDA_R0A = 0x0A +RDA_R0B = 0x0B + +class RDA5807(object): + ''' + 收音机RDA5807类 + 开放接口:_rda_init(),fm_enable(),next_chanl(),seek_channel(),freq_set(freq),seekth_set(reei) + rssi_get(),seek_direction(dir),vol_set(vol),mute_set(),bass_set(bass) + ''' + def __init__(self,rdaclk,rdadio): + self.CLK = Pin(rdaclk, Pin.OUT, Pin.PULL_DISABLE, 1) # PL5NF001 CLK + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) # PL5NF001 DIO + self._rda_init() + + def _delay_ms(self, ms): + time.sleep_ms(ms) + + def _delay_us(self, num): + pass + + def _start_signal(self): + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) + self.DIO.write(1) + self.CLK.write(1) + self._delay_us(5) + self.DIO.write(0) + self._delay_us(5) + self.CLK.write(0) + self._delay_us(5) + + def _stop_signal(self): + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) + self.CLK.write(0) + self._delay_us(2) + self.DIO.write(0) + self._delay_us(2) + self.CLK.write(1) + self._delay_us(2) + self.DIO.write(1) + self._delay_us(2) + + def _ack(self, is_ack): + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) + self.DIO.write(is_ack) + self._delay_us(2) + self.CLK.write(1) + self._delay_us(4) + self.CLK.write(0) + + def _wait_ack(self): + i = 0 + self.CLK.write(0) + self._delay_us(2) + self.DIO = Pin(rdadio, Pin.IN, Pin.PULL_DISABLE, 1) + self._delay_us(2) + + while (self.DIO.read()): + i += 1 + if i > 2000: + #self._stop_signal() + print('iic stop') + self.CLK.write(0) + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) + return 1 + self._delay_us(2) + self.CLK.write(1) + self._delay_us(2) + self.CLK.write(0) + #self._delay_us(2) + return 0 + + def _write_data(self, data): + self.DIO = Pin(rdadio, Pin.OUT, Pin.PULL_DISABLE, 1) + j = 0 + for j in range(0,8): + self.CLK.write(0) + self._delay_us(2) + if data & 0x80: + self.DIO.write(1) + else: + self.DIO.write(0) + data <<= 1 + self._delay_us(2) + self.CLK.write(1) + self._delay_us(2) + + self.CLK.write(0) + + self._wait_ack() + + def _read_byte(self, ack): + self.DIO = Pin(rdadio, Pin.IN, Pin.PULL_DISABLE, 1) + recive = 0 + time.sleep_ms(12) + for i in range(0, 8): + recive <<= 1 + self.CLK.write(0) + self._delay_us(2) + self.CLK.write(1) + self._delay_us(2) + level = self.DIO.read() + if level == 1: + recive |= 1 + self.CLK.write(0) + self._ack(ack) + return recive + + + def _ReadReg(self, regaddr): + self._start_signal() + self._write_data(RDA_WRITE) + self._write_data(regaddr) + self._start_signal() + self._write_data(RDA_READ) + buf = self._read_byte(ACK) + buf <<= 8 + buf = buf | self._read_byte(NACK) + self._stop_signal() + print("read reg =",buf) + return buf + + def _WriteReg(self, reg, val): + self._start_signal() + self._write_data(RDA_WRITE) + self._write_data(reg) + self._write_data(val >> 8) + self._write_data(val & 0xFF) + self._stop_signal() + + def vol_set(self, vol): + ''' + 音量设置 + :param vol: 0-15 + ''' + temp = self._ReadReg(RDA_R05) + print("vol set:",temp) + temp &= 0xfff0 #0-3bit 音量 + self._WriteReg(RDA_R05,vol|temp) + + def mute_set(self, mute): + ''' + 静音设置 + :param mute: 1 静音 0 不静音 + ''' + tmp = self._ReadReg(RDA_R02) + if(mute == 0): + tmp |= (1<<14) #14bit置1,不静音 + else: + tmp &= ~(1<<14) + print("mute set:", tmp) + self._WriteReg(RDA_R02, tmp) + + def bass_set(self, bass): + ''' + 声音低频 + :param bass: + ''' + tmp = self._ReadReg(RDA_R02) + if(bass): + tmp |= (1<<12) + else: + tmp &= ~(1<<12) + print("bass set:", tmp) + self._WriteReg(RDA_R02, tmp) + + def rssi_get(self): + ''' + 信号强度获取 15-9bit + :return 信号强度 + ''' + tmp = self._ReadReg(RDA_R0B) + tmp = (tmp >> 9) & 0x7f + return tmp + + def seekth_set(self,rssi): + ''' + 自动搜台信号阈值强度 14-8bit + :param rssi: 0-15 默认为8 数值越低搜到的台越多 + ''' + rssi = rssi & 0xf + tmp = self._ReadReg(RDA_R05) + tmp &= ~(0xf<<8) + tmp |= (rssi<<8) + self._WriteReg(RDA_R05, tmp) + + def seek_direction(self,dir): + ''' + 搜台方向 + :param dir: 1:向上搜索 0:向下搜索 + ''' + tmp = self._ReadReg(RDA_R02) + tmp &= ~(1<<9) + if(dir == 1): + tmp |= (1<<9) + else: + tmp |= (0<<9) + #较旧版本修改点 写入寄存器RDA_R02 + self._WriteReg(RDA_R02, tmp) + + def freq_set(self, freq): + ''' + 频率设置 单位是10Khz + :param freq: 6500~10800 + ''' + tmp = self._ReadReg(RDA_R03) + tmp &= 0x001F + band = (tmp>>2)&0x03 + spc = tmp & 0x03 + + if(spc == 0): + spc = 10 + elif(spc == 1): + spc = 20 + else: + spc = 5 + + if(band == 0): + fbtm = 8700 + elif(band == 1 or (band == 2)): + fbtm = 7600 + else: + fbtm = self._ReadReg(0x53) + fbtm *= 10 + + if(freq < fbtm): + print("freq < fbtm") + return + + chan = int((freq - fbtm)/spc) + chan &= 0x3ff + tmp |= (chan<<6) + tmp |= (1<<4) + self._WriteReg(RDA_R03, tmp) + time.sleep_ms(20) + + def seek_channel(self): + ''' + 自动搜台 + ''' + tmp = self._ReadReg(RDA_R02) + tmp |= (1<<8) + self._WriteReg(RDA_R02, tmp) + while((self._ReadReg(RDA_R0A) & (1<<14)) == 0): + time.sleep_ms(10) + + tmp = (self._ReadReg(RDA_R0A) & 0x3ff) *100000 + 87000000 + print("seek channel:",tmp) + return tmp/10000 + + def fm_enable(self,flag): + ''' + 使能芯片 + :param flag: 1.使能 0:禁用 + ''' + tmp = self._ReadReg(RDA_R02) + if(flag == 1): + tmp |= 1 + + if(flag == 0): + tmp &= ~(0x1) + + self._WriteReg(RDA_R02,tmp) + + def _rda_init(self): + ''' + RDA 初始化 + ''' + self._WriteReg(RDA_R02, 0x0002) + time.sleep_ms(30) + self._WriteReg(RDA_R02, 0xd281) + self._WriteReg(RDA_R03, 0x0000) + self._WriteReg(RDA_R04, 0x0040) + self._WriteReg(RDA_R05, 0x8880) + + self.fm_enable(1) + + def next_chanl(self): + ''' + 播放下个电台 + ''' + freq = self.seek_channel() + + if((self._ReadReg(RDA_R0B)>>8) & 0x01): + print("is chan", freq) + + if((self._ReadReg(RDA_R0A)&0x01)): + print("SF = 1") + self.freq_set(freq) + + + +if __name__ == '__main__': + test_pm = RDA5807(rdaclk = Pin.GPIO2,rdadio = Pin.GPIO3) + test_pm._rda_init() + print("init finish. ") + test_pm.seek_channel() + print("channel seeking...") + test_pm.vol_set(15) + print('vol seted to 15.') + test_pm.fm_enable(0) + print("radio forbid.") + + diff --git a/libraries/SGP40/Sensirion_Gas-Sensors_SGP40_Datasheet.pdf b/libraries/SGP40/Sensirion_Gas-Sensors_SGP40_Datasheet.pdf new file mode 100644 index 0000000..0ff488b Binary files /dev/null and b/libraries/SGP40/Sensirion_Gas-Sensors_SGP40_Datasheet.pdf differ diff --git a/libraries/TM1650/TM-TM1650.pdf b/libraries/TM1650/TM-TM1650.pdf new file mode 100644 index 0000000..571836f Binary files /dev/null and b/libraries/TM1650/TM-TM1650.pdf differ diff --git a/libraries/TM1650/tm1650.py b/libraries/TM1650/tm1650.py new file mode 100644 index 0000000..e28a6e4 --- /dev/null +++ b/libraries/TM1650/tm1650.py @@ -0,0 +1,291 @@ +from machine import Pin +import _thread +import utime +#from usr.cutils import CPower +PINS = [getattr(Pin,"GPIO"+str(i)) for i in range(1,18) ] + +class Tm1650(object): + ''' + Tm1650类 + 开放接口:on(),off(),all_clear(),light(self, addr, data,is_point=False,is_auto=False), + clear_bit(bit),all_show(),show_num(num),show_str(st),show_dp(bit) + circulate_show(st) + ''' + CONTROL_CMD = 0x48 + SCANKEY_CMD = 0x49 + + DISPLAY_ON = 0x11 + DISPLAY_OFF = 0x10 + a = 0x01 + b = 0x02 + c = 0x04 + d = 0x08 + e = 0x10 + f = 0x20 + g = 0x40 + dp = 0x80 + DATA_ADDR1 = 0x68 + DATA_ADDR2 = 0x6A + DATA_ADDR3 = 0x6C + DATA_ADDR4 = 0x6E + DIO_PIN = Pin.GPIO10 + CLK_PIN = Pin.GPIO13 + + LIGHT_MAPPING = { + 1: DATA_ADDR1, + 2: DATA_ADDR2, + 3: DATA_ADDR3, + 4: DATA_ADDR4, + 5: CONTROL_CMD + } + # "-": 0x40, + DISPLAY_MAPPING = {"0": a | b | c | d| e | f, "1": b | c, "2": a | b | g | e | d, "3": a | b | g | c | d, + "4": f |g | b | c, "5": a | f | g | c | d, "6": a | f | g | c | d | e, "7": a | b | c, + "8": a | b | c | d | e | f | g, "9": a | b | c | d | f | g, + "A": a | b | c | e | f | g, "b": c | d | e | f | g, "C":a|f|e|d,"c": g|e|d,"d": b | c | d | e | g, + "E": a | d | e | f | g, "F": a | e | f | g, "on": DISPLAY_ON, "p": a | b | g | f | e,"P":a | b | g | f | e, + "S": a | f | g | c|d, "r": g | e, "t": f | g | e | d, "i": b|c,"s": a|f | g | c|d, + "L": f | e | d, "H": f | e | g | b | c, "n": e | g | c,"h":f | e | g | c,"I":f|e,"J": b|c|d|e,"O": c | d | e | g, + "off": DISPLAY_OFF,"cl": 0x00, " ":0x00,"4g": a, "cool": f, "alarm": e, "wifi": d, "def": dp,".":dp, + "-": g, 0x00: 0x00, "_": b|g|e} + + def __init__(self, dio=None, clk=None): + if dio == clk: + dio = clk = None + if dio and dio in PINS: + self._dio_PIN = dio + if clk and clk in PINS: + self._clk_PIN = clk + self._dio = Pin(self._dio_PIN, Pin.OUT, Pin.PULL_DISABLE, 1) # Tm1650 DIO + self._clk = Pin(self._clk_PIN, Pin.OUT, Pin.PULL_DISABLE, 1) # Tm1650 CLK + self._light_lock = _thread.allocate_lock() + + # def _delay_us(self, num=3000): + def _delay_us(self, num=300): + # utime.sleep_ms(1) + while num > 0: + num = num -1 + + def _start_signal(self): + self._clk.write(1) + self._delay_us(200) + self._dio.write(1) + self._delay_us(200) + self._dio.write(0) + self._delay_us(200) + self._clk.write(0) + + def _stop_signal(self): + self._dio.write(0) + self._delay_us(200) + self._clk.write(1) + self._delay_us(200) + self._dio.write(1) + self._delay_us(200) + self._clk.write(0) + self._delay_us(200) + self._dio.write(0) + + def _wait_ack(self): + # self._dio.write(1) + self._dio = Pin(self._dio_PIN, Pin.IN, Pin.PULL_PU, 0) + # self._delay_us() + self._clk.write(1) + self._delay_us() + i = 0 + while (self._dio.read()): + i += 1 + print("i = ",i) + if i > 700: + self._dio = Pin(self._dio_PIN, Pin.OUT, Pin.PULL_DISABLE, 1) # Tm1650 DIO + self._clk.write(0) + self._delay_us() + self._stop_signal() + raise Exception("数据通信错误") + self._clk.write(0) + self._delay_us() + self._dio = Pin(self._dio_PIN, Pin.OUT, Pin.PULL_DISABLE, 1) # Tm1650 DIO + + def _write_data(self, data): + self._clk.write(0) + self._delay_us(200) + for j in range(8): + if data & 0x80: + self._dio.write(1) + else: + self._dio.write(0) + self._delay_us() + self._clk.write(1) + self._delay_us() + self._clk.write(0) + data <<= 1 + + def light(self, addr, data,is_point=False,is_auto=False): + ''' + 写数据命令或往显存地址写显示数据 + :param addr: 寄存器地址 + :param data: 写入的数据 + :param is_point: 是否是点 + :param is_auto: 是否需要字符转化 + ''' + try: + self._light_lock.acquire() + if is_auto: + if data not in self.DISPLAY_MAPPING: + data = "0" + data = self.DISPLAY_MAPPING[data] + + if is_point: + data = data | self.DISPLAY_MAPPING["."] + self._start_signal() + self._write_data(self.LIGHT_MAPPING[addr]) + self._wait_ack() + self._write_data(data) + self._wait_ack() + self._stop_signal() + except Exception as e: + print(e,addr,data,_thread.get_ident()) + # if addr ==2 or addr==3: + #CPower.restart() + finally: + self._light_lock.release() + + def on(self): + times = 3 + while times > 0 and self.light(5, "on", is_auto=True): + # self.light(5, "on", is_auto=True) + utime.sleep(1) + times = times - 1 + + def off(self): + self.light(5, "off", is_auto=True) + + def all_clear(self): + ''' + 清除全部显示 + ''' + try: + for i in range(1,5): + self.light(i, "cl", is_auto=True) + except Exception as e: + print(e) + + def clear_bit(self,bit): + ''' + 清除一位显示 + ''' + if bit > 4 or bit < 1: + return -1 + try: + self.light(bit, "cl", is_auto=True) + except Exception as e: + print(e) + + def all_show(self): + ''' + 全显 + ''' + try: + self.light(1, 0xff) + self.light(2, 0xff) + self.light(3, 0xff) + self.light(4, 0xff) + except Exception as e: + print(e) + + def show_num(self, num): + ''' + 显示数字,不满四位的靠右显示 + :param num: 数字 -999 ~ 9999 + :return: -1:error 0:success + ''' + if num < -999 or num > 9999: + return -1 + try: + if num < 0: + self.light(1,'-',is_auto=True) + num = -num + else: + self.light(1,str((num // 1000) % 10),is_auto=True) + self.light(2, str((num // 100) % 10),is_auto=True) + self.light(3, str((num // 10) % 10),is_auto=True) + self.light(4, str(num % 10),is_auto=True) + return 0 + except Exception as e: + print(e) + + def show_str(self,st): + ''' + 显示字符串,不足四位的靠右显示 + :param st: 字符串 + :return: -1:error 0:success + ''' + if len(st) > 4: + return -1 + bits = len(st) + try: + for ch in st[::1]: + if ch not in self.DISPLAY_MAPPING: + return -1 + else: + self.light(5 - bits,ch,is_auto=True) + bits -= 1 + return 0 + except Exception as e: + print(e) + + def show_dp(self, bit=1): + ''' + 显示点 + :param bit: 显示在第几位,范围1-4,默认1 + :return: -1:error 0:success + ''' + if bit > 4 or bit < 1: + return -1 + self.light(bit,'.',is_auto=True) + return 0 + + def circulate_show(self,st): + ''' + 循环显示字符串或数字 + :param st: 字符串12字节以内 + :return: -1:字符串过长 + ''' + show_lst = [] + circle = 0 + if len(st) > 4: + new_str = st + st + for i in range(len(st)): + show_lst.append(new_str[i:i+4]) + else: + null_count = 4 - len(st) + new_str = ' ' * null_count + st + new_str += new_str + for i in range(4): + show_lst.append(new_str[i:i+4]) + while 1: + self.show_str(show_lst[circle]) + if circle == len(show_lst) - 1: + circle = 0 + else: + circle += 1 + utime.sleep(0.5) + +if __name__ == "__main__": + tube = Tm1650(Pin.GPIO13, Pin.GPIO12) #600U PIN60,PIN59 + tube.on() + tube.all_show() + utime.sleep(1) + tube.clear_bit(3) + utime.sleep(1) + tube.all_clear() + utime.sleep(1) + tube.show_dp(3) + utime.sleep(1) + tube.show_str("PPJ") + utime.sleep(1) + tube.show_num(-537) + utime.sleep(1) + tube.show_num(8537) + utime.sleep(1) + tube.circulate_show("AbCdEFH") diff --git a/libraries/TSL2591/TSL2591.pdf b/libraries/TSL2591/TSL2591.pdf new file mode 100644 index 0000000..ea3be8d Binary files /dev/null and b/libraries/TSL2591/TSL2591.pdf differ diff --git a/libraries/ch395/ch395.PDF b/libraries/ch395/ch395.PDF new file mode 100644 index 0000000..4d44cd5 Binary files /dev/null and b/libraries/ch395/ch395.PDF differ diff --git "a/libraries/ch423s/C111663_I-O\346\211\251\345\261\225\345\231\250_CH423S_\350\247\204\346\240\274\344\271\246_WCH(\345\215\227\344\272\254\346\262\201\346\201\222)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" "b/libraries/ch423s/C111663_I-O\346\211\251\345\261\225\345\231\250_CH423S_\350\247\204\346\240\274\344\271\246_WCH(\345\215\227\344\272\254\346\262\201\346\201\222)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" new file mode 100644 index 0000000..b506015 Binary files /dev/null and "b/libraries/ch423s/C111663_I-O\346\211\251\345\261\225\345\231\250_CH423S_\350\247\204\346\240\274\344\271\246_WCH(\345\215\227\344\272\254\346\262\201\346\201\222)I_O\346\211\251\345\261\225\345\231\250\350\247\204\346\240\274\344\271\246.PDF" differ diff --git a/libraries/ch423s/ch423s.py b/libraries/ch423s/ch423s.py new file mode 100644 index 0000000..5b33ee6 --- /dev/null +++ b/libraries/ch423s/ch423s.py @@ -0,0 +1,254 @@ +''' +@Author: Stephen.Gao +@Date: 2022-04-6 +@Description: GH423S IO ex driver + +Copyright 2022 - 2022 quectel +''' +from machine import Pin +import utime + +GPIO_IN = 0 +GPIO_OUT = 1 + +#次i2c设备没有地址 +#每个cmd就是一个地址 + +CH423_SYS_CMD = 0x48 #系统参数命令地址 +BIT_X_INT = 0x08 #使能输入电平变化中断,为0禁止输入电平变化中断;为1并且DEC_H为0允许输出电平变化中断 +BIT_DEC_H = 0x04 #控制开漏输出引脚高8位的片选译码 +BIT_DEC_L = 0x02 #控制开漏输出引脚低8位的片选译码 +BIT_IO_OE = 0x01 #gpio引脚的输出使能,为1允许输出 +BIT_OD_EN = 0x10 #使能输出引脚 OC15~OC0 的开漏输出 + +CH423_OC_L_CMD = 0x44 #设置低 8 位通用输出命令(默认模式推挽) +BIT_OC0_L_DAT = 0x01 #OC0为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC1_L_DAT = 0x02 #OC1为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC2_L_DAT = 0x04 #OC2为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC3_L_DAT = 0x08 #OC3为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC4_L_DAT = 0x10 #OC4为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC5_L_DAT = 0x20 #OC5为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC6_L_DAT = 0x40 #OC6为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) +BIT_OC7_L_DAT = 0x80 #OC7为0则使引脚输出低电平,为1则引脚输出高电平(开漏不输出) + +CH423_OC_H_CMD = 0x46 #设置高 8 位通用输出命令 + +CH423_SET_IO_CMD = 0x60 #设置双向输入输出命令 + +CH423_RD_IO_CMD = 0x4D #读取双向输入输出命令 + + +class Ch423s(object): + def __init__(self,clk,dio): + self._pin_dio = dio + self._pin_clk = clk + self._clk = Pin(clk, Pin.OUT, Pin.PULL_DISABLE, 1) + self._dio = Pin(dio, Pin.OUT, Pin.PULL_DISABLE, 1) + self._write_reg(CH423_SYS_CMD,0x00) #设置系统参数命令 + + def delay_ms(self, ms): + utime.sleep_ms(ms) + + def delay_us(self, num): + pass + + def _start_signal(self): + self._dio = Pin(self._pin_dio, Pin.OUT, Pin.PULL_DISABLE, 1) + self._dio.write(1) + self._clk.write(1) + self.delay_us(5) + self._dio.write(0) + self.delay_us(5) + self._clk.write(0) + self.delay_us(5) + + def _stop_signal(self): + self._dio = Pin(self._pin_dio, Pin.OUT, Pin.PULL_DISABLE, 1) + self._clk.write(0) + self.delay_us(2) + self._dio.write(0) + self.delay_us(2) + self._clk.write(1) + self.delay_us(2) + self._dio.write(1) + self.delay_us(2) + + def ack(self, is_ack): + self._dio = Pin(self._pin_dio, Pin.OUT, Pin.PULL_DISABLE, 1) + self._dio.write(is_ack) + self.delay_us(2) + self._clk.write(1) + self.delay_us(4) + self._clk.write(0) + + def _wait_ack(self): + i = 0 + self._clk.write(0) + self.delay_us(2) + self._dio = Pin(self._pin_dio, Pin.IN, Pin.PULL_DISABLE, 1) + self.delay_us(2) + + while (self._dio.read()): + i += 1 + if i > 2000: + # self._stop_signal() + print('iic stop') + self._clk.write(0) + self._dio = Pin(self._pin_dio, Pin.OUT, Pin.PULL_DISABLE, 1) + return 1 + self.delay_us(2) + self._clk.write(1) + self.delay_us(2) + self._clk.write(0) + # self.delay_us(2) + return 0 + + def _write_byte(self, data): + self._dio = Pin(self._pin_dio, Pin.OUT, Pin.PULL_DISABLE, 1) + for j in range(0, 8): + self._clk.write(0) + self.delay_us(2) + # 从高位开始发 + if data & 0x80: + self._dio.write(1) + else: + self._dio.write(0) + data <<= 1 + self.delay_us(2) + self._clk.write(1) + self.delay_us(2) + self._clk.write(0) + self._wait_ack() + # print("#") + + def _read_byte(self): + # self._dio = Pin(RDADIO, Pin.IN, Pin.PULL_DISABLE, 1) + self._dio = Pin(self._pin_dio, Pin.IN, Pin.PULL_DISABLE, 1) + recive = 0 + utime.sleep_ms(12) + for i in range(0, 8): + recive <<= 1 + self._clk.write(0) + self.delay_us(2) + self._clk.write(1) + self.delay_us(2) + level = self._dio.read() + if level == 1: + recive |= 1 + self._clk.write(0) + self.ack(1) + return recive + + def _read_reg(self, cmd): + self._start_signal() + self._write_byte(cmd) + r_data = self._read_byte() + self._stop_signal() + return r_data + + def _write_reg(self, cmd, val): + self._start_signal() + self._write_byte(cmd) + self._write_byte(val) + self._stop_signal() + + def reset(self): + self._write_reg(CH423_SYS_CMD, 0x00) + + def config(self,dir=GPIO_IN,int=0,odr=0): + ''' + 配置双向输入输出引脚 IO7~IO0的输出使能 , + IO_OE输入电平变化中断使能 X_INT, + 输出引脚 OC15~OC0 开漏输出使能 OD_EN + :param dir: gpio方向 + :param int: 输入电平变化中断使能 + :param odr: 开漏输出使能 + ''' + if dir not in (0,1) or int not in (0,1) or odr not in (0,1): + return -1 + w_byte = 0x00 + if dir: + w_byte = w_byte | BIT_IO_OE + if int: + w_byte = w_byte | BIT_X_INT + if odr: + w_byte = w_byte | BIT_OD_EN + self._write_reg(CH423_SYS_CMD, w_byte) + return 0 + + def gpio_pin(self, pin, value=1): + ''' + 确保是输出模式,gpio引脚设置 + :param pin: 引脚号: 0-7 + :param value: 0 or 1 + ''' + if pin not in range(8) or value not in (0,1): + return -1 + r_byte = self.read_gpio() + if value: + bit_io = 1 << pin + w_byte = r_byte | bit_io + else: + bit_io = 1 << pin + w_byte = r_byte & ~bit_io + self._write_reg(CH423_SET_IO_CMD, w_byte) + return 0 + + def gpo_h(self,value): + ''' + 通用输出高8位整体设值 + :param value: 高八位电平高低 + ''' + if value not in range(256): + return -1 + self._write_reg(CH423_OC_H_CMD, value) + return 0 + + def gpo_l(self,value): + ''' + 通用输出低8位整体设值 + :param value: 低八位电平高低 + ''' + if value not in range(256): + return -1 + self._write_reg(CH423_OC_L_CMD, value) + return 0 + + def gpio(self,value): + ''' + 确保是输出模式,gpio 8位整体设值 + :param value: 八位电平高低 + ''' + if value not in range(256): + return -1 + self._write_reg(CH423_SET_IO_CMD, value) + return 0 + + def read_gpio(self): + ''' + 读取 IO7~IO0 引脚的当前状态 + :return: 当 IO_OE 为 0 时为获取输入状态,否则为获取输出状态 + ''' + r_byte = self._read_reg(CH423_RD_IO_CMD) + return r_byte + +if __name__ == "__main__": + ch423 = Ch423s(Pin.GPIO12,Pin.GPIO13) + print("init success. ") + utime.sleep(1) + #ch423.config(odr=1) + # for i in range(10): + # ch423.gpo_h(0x00) + # utime.sleep(0.1) + # ch423.gpo_h(0x01) + # utime.sleep(0.1) + ch423.config(dir=1) + print("gpio all set output.") + for i in range(10): + # ch423.gpio(0xff) + ch423.gpio_pin(pin=5,value=1) + utime.sleep(0.1) + print(ch423.read_gpio()) + ch423.gpio(0x00) + utime.sleep(0.1) + print(ch423.read_gpio()) \ No newline at end of file diff --git a/libraries/dm9051/DAVICOM-DM9051.pdf b/libraries/dm9051/DAVICOM-DM9051.pdf new file mode 100644 index 0000000..069f125 Binary files /dev/null and b/libraries/dm9051/DAVICOM-DM9051.pdf differ diff --git a/libraries/w5500/w5500_ds_v13c.pdf b/libraries/w5500/w5500_ds_v13c.pdf new file mode 100644 index 0000000..ef832f0 Binary files /dev/null and b/libraries/w5500/w5500_ds_v13c.pdf differ diff --git a/libraries/xpt2046/XPT2046-CH.pdf b/libraries/xpt2046/XPT2046-CH.pdf new file mode 100644 index 0000000..743a0d5 Binary files /dev/null and b/libraries/xpt2046/XPT2046-CH.pdf differ diff --git a/libraries/yt8512/yt8512c_yt8512h_datasheet.pdf b/libraries/yt8512/yt8512c_yt8512h_datasheet.pdf new file mode 100644 index 0000000..2f5ebd9 Binary files /dev/null and b/libraries/yt8512/yt8512c_yt8512h_datasheet.pdf differ