/
IArtuSI
/
MCP-2515-MicroPython
Обзор
Документация
Войти
/
IArtuSI
/
MCP-2515-MicroPython
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
3
CI/CD
Аналитика
Безопасность
testing
MCP_Main.py
195 строк
8 KB
IArtuSI
V 0.3.3b
28 апр 2026, 07:19
28 апр 2026, 07:19
38d2fa0
Код
Авторство
О чём код?
from machine import SPI, Pin _SPI_Pins = { # SPI_ID [SCK, MOSI, MISO, CS] 0 : [Pin('GP2'), Pin('GP3'), Pin('GP0')], 1 : [Pin('GP10'), Pin('GP11'), Pin('GP8')] } _can_speeds = { # [PropSeg, PhaseSeg1, PhaseSeg2, SJW, BRP] '100k' : [3,9,7,4,4], '125k' : [2,7,6,2,4], '250k' : [2,7,6,2,2], '500k' : [1,3,3,1,2]} _can_modes = ['Config', 'Normal', 'Sleep', 'Listen', 'Loop'] _can_filter_adress = {0 : 0x00, 1 : 0x04, 2 : 0x08, 3 : 0x10, 4 : 0x14, 5 : 0x18} _can_mask_adress = {0 : 0x20, 1 : 0x24} _pass_func = lambda x: x class mcp_can(): def __init__(self, SPI_ID : int, SPI_CS : Pin, inter : Pin = Pin('GP10'), func_dict : dict = {} ) -> None: SPI_conf = _SPI_Pins[SPI_ID] self.spi = SPI(SPI_ID, baudrate=1000000, sck=SPI_conf[0], mosi=SPI_conf[1], miso=SPI_conf[2]) self.cs = SPI_CS self.func_dict = func_dict self.cs.on() if len(self.func_dict) != 0: print('irq Activated!') inter.irq(trigger=Pin.IRQ_FALLING, handler=self._inter_controll) def _send_spi(self, data : list, rx_len = 0) -> list[int]: self.cs.off() data_raw = bytes(data) self.spi.write(data_raw) # print(f'data_raw {data_raw}') result = self.spi.read(rx_len) self.cs.on() return [b for b in result] def _inter_controll(self, pin) -> None: int_flag = self.inter_flag() if int_flag[0]: self.func_dict['RX0_INT']() if int_flag[1]: self.func_dict['RX1_INT']() if int_flag[2]: self.func_dict['TX0_INT']() if int_flag[3]: self.func_dict['TX1_INT']() if int_flag[4]: self.func_dict['TX2_INT']() if int_flag[5]: self.func_dict['ERR_INT']() if int_flag[6]: self.func_dict['WAK_INT']() if int_flag[7]: self.func_dict['MER_INT']() def _read_can_mode(self) -> str: data_to_send = [0x03, 0xEF] result = self._send_spi(data_to_send, 1)[0] >> 5 if result == 0b000 : return _can_modes[1] if result == 0b100 : return _can_modes[0] if result == 0b001 : return _can_modes[2] if result == 0b011 : return _can_modes[3] if result == 0b010 : return _can_modes[4] return 'Mode error!' def _id_to_bytes_list(self, id) -> list[int]: raw_id = (id << 5).to_bytes(2) return [raw_id[0], raw_id[1]] def rts(self, tx_buf : list = [0,0,0]) -> None: # TX_buf = [TX0, TX1, TX2] command = 0x80 if tx_buf[0] == 1: command = command | 0x01 if tx_buf[1] == 1: command = command | 0x02 if tx_buf[2] == 1: command = command | 0x04 self._send_spi([command]) def reset_can(self) -> None: self._send_spi([0xC0]) def status(self) -> list[int] : raw_status = self._send_spi([0xA0], 1)[0] status_list = [] #print(f'raw_status {raw_status}') for i in range(8): status_list.append(raw_status & (1 >> i)) return status_list def load_message(self, id : int, data : list, tx_id : int = 2, short_msg : bool = False, extend_id : bool = False, ) -> None: data_to_send = [0x40] if not extend_id: if short_msg: data_to_send[0] = data_to_send[0] | 0x01 data_to_send[0] = data_to_send[0] | tx_id << 1 if id <= 0x7FF: dlc = len(data) id_raw = (id << 5).to_bytes(2) if not short_msg: data_to_send.extend([id_raw[0], id_raw[1], 0x00, 0x00, dlc]) data_to_send.extend(data) else: print('Error: ID is wrong') # print(data_to_send) self._send_spi(data_to_send) def read_message(self, rx_id : int, short_message : bool = False) -> dict: data_to_send = [0x90] if short_message : data_to_send[0] = data_to_send[0] | 0x01 if rx_id == 0 : data_to_send[0] = data_to_send[0] | 0x00 elif rx_id == 1 : data_to_send[0] = data_to_send[0] | 0x02 raw_data = self._send_spi(data_to_send, 8 if short_message else 13) if not short_message: data = {'id' : ((raw_data[0] << 8 | raw_data[1]) >> 5), 'dlc' : raw_data[4], 'data' : raw_data[5:]} else: data = {'data' : raw_data} return data def set_can_speed(self, speed : str) -> None: if speed in _can_speeds: s = _can_speeds[speed] # [PropSeg, PhaseSeg1, PhaseSeg2, SJW, BRP] dat_list = bytearray(4) dat_list[0] += (s[2] - 1) dat_list[1] += (1 << 7) + ((s[1] - 1) << 3) + (s[0] - 1) dat_list[2] += ((s[3] - 1) << 6) + (int(s[4] / 2) - 1) self._send_spi([0x02, 0x28, dat_list[0], dat_list[1], dat_list[2]]) else: print('Error: Speed is wrong') def set_interrupt(self, mode : list = [0,0,0,0,0,0,0,0]) -> None: #mode = [RX0IE, RX1IE, TX0IE, TX1IE, TX2IE, ERRIE, WAKIE, MERRE] data_to_send = [0x02, 0x2B, 0x00] for i, int in enumerate(mode): if int: data_to_send[2] = data_to_send[2] | 0x01 << i self._send_spi(data_to_send) def mode_controll(self, mode : str = 'Config', abort_tx : bool = False, one_shot : bool = False, clk_out : bool = False, clk_pre : int = 1 ) -> None: data_to_send = [0x02, 0xFF, 0x00] if mode in _can_modes: if mode == 'Config' : data_to_send [2] = data_to_send[2] | 0b100 << 5 elif mode == 'Normal' : data_to_send [2] = data_to_send[2] | 0b000 << 5 elif mode == 'Sleep' : data_to_send [2] = data_to_send[2] | 0b001 << 5 elif mode == 'Listen' : data_to_send [2] = data_to_send[2] | 0b011 << 5 elif mode == 'Loop' : data_to_send [2] = data_to_send[2] | 0b010 << 5 else: print('Error: Mode is wrong') if abort_tx: data_to_send [2] = data_to_send[2] | 0x01 << 4 if one_shot: data_to_send [2] = data_to_send[2] | 0x01 << 3 if clk_out : data_to_send [2] = data_to_send[2] | 0x01 << 2 if clk_pre in [1,2,4,8]: if clk_pre == 1 : data_to_send [2] = data_to_send[2] | 0x00 elif clk_pre == 2 : data_to_send [2] = data_to_send[2] | 0x01 elif clk_pre == 4 : data_to_send [2] = data_to_send[2] | 0x02 elif clk_pre == 8 : data_to_send [2] = data_to_send[2] | 0x03 else: print('Error : Clock Prescaller is wrong') self._send_spi(data_to_send) #print(f'set mode {self._send_spi([0x03, 0xEE], 1)}') def inter_flag(self) -> list[int] : raw_flag = self._send_spi([0x03, 0x2C], 1)[0] flag_list = [] #print(f'raw_status {raw_status}') for i in range(8): flag_list.append(raw_flag & (1 >> i)) return flag_list def set_filter(self, filter_id = 0, filter = 0x000) -> None: if self._read_can_mode() != _can_modes[0]: print('MCp in not Config mode') return data_to_send = [0x02, _can_filter_adress[filter_id]] data_to_send.extend(self._id_to_bytes_list(filter)) self._send_spi(data_to_send) def set_mask(self, mask_id = 0, mask = 0x000) -> None: if self._read_can_mode() != _can_modes[0]: print('MCP in not Config mode') return data_to_send = [0x02, _can_mask_adress[mask_id]] data_to_send.extend(self._id_to_bytes_list(mask)) self._send_spi(data_to_send)