久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4762|回復: 1
收起左側

Micropython SD卡驅動源碼(無文件系統 按塊號存取)

[復制鏈接]
ID:313579 發表于 2018-4-22 10:58 | 顯示全部樓層 |閱讀模式
SPI協議 micropython  無文件系統  按塊號存取

Micropython源程序如下:
  1. """
  2. MicroPython driver for SD cards using SPI bus.

  3. Requires an SPI bus and a CS pin.  Provides readblocks and writeblocks
  4. methods so the device can be mounted as a filesystem.

  5. Example usage on pyboard:

  6.     import pyb, sdcard, os
  7.     sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
  8.     pyb.mount(sd, '/sd2')
  9.     os.listdir('/')

  10. Example usage on ESP8266:

  11.     import machine, sdcard, os
  12.     sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
  13.     os.mount(sd, '/sd')
  14.     os.listdir('/')

  15. """

  16. from micropython import const
  17. import time


  18. _CMD_TIMEOUT = const(100)

  19. _R1_IDLE_STATE = const(1 << 0)
  20. #R1_ERASE_RESET = const(1 << 1)
  21. _R1_ILLEGAL_COMMAND = const(1 << 2)
  22. #R1_COM_CRC_ERROR = const(1 << 3)
  23. #R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
  24. #R1_ADDRESS_ERROR = const(1 << 5)
  25. #R1_PARAMETER_ERROR = const(1 << 6)
  26. _TOKEN_CMD25 = const(0xfc)
  27. _TOKEN_STOP_TRAN = const(0xfd)
  28. _TOKEN_DATA = const(0xfe)


  29. class SDCard:
  30.     def __init__(self, spi, cs):
  31.         self.spi = spi
  32.         self.cs = cs

  33.         self.cmdbuf = bytearray(6)
  34.         self.dummybuf = bytearray(512)
  35.         self.tokenbuf = bytearray(1)
  36.         for i in range(512):
  37.             self.dummybuf[i] = 0xff
  38.         self.dummybuf_memoryview = memoryview(self.dummybuf)

  39.         # initialise the card
  40.         self.init_card()

  41.     def init_spi(self, baudrate):
  42.         try:
  43.             master = self.spi.MASTER
  44.         except AttributeError:
  45.             # on ESP8266
  46.             self.spi.init(baudrate=baudrate, phase=0, polarity=0)
  47.         else:
  48.             # on pyboard
  49.             self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)

  50.     def init_card(self):
  51.         # init CS pin
  52.         self.cs.init(self.cs.OUT, value=1)

  53.         # init SPI bus; use low data rate for initialisation
  54.         self.init_spi(100000)

  55.         # clock card at least 100 cycles with cs high
  56.         for i in range(16):
  57.             self.spi.write(b'\xff')

  58.         # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
  59.         for _ in range(5):
  60.             if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
  61.                 break
  62.         else:
  63.             raise OSError("no SD card")

  64.         # CMD8: determine card version
  65.         r = self.cmd(8, 0x01aa, 0x87, 4)
  66.         if r == _R1_IDLE_STATE:
  67.             self.init_card_v2()
  68.         elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
  69.             self.init_card_v1()
  70.         else:
  71.             raise OSError("couldn't determine SD card version")

  72.         # get the number of sectors
  73.         # CMD9: response R2 (R1 byte + 16-byte block read)
  74.         if self.cmd(9, 0, 0, 0, False) != 0:
  75.             raise OSError("no response from SD card")
  76.         csd = bytearray(16)
  77.         self.readinto(csd)
  78.         if csd[0] & 0xc0 == 0x40: # CSD version 2.0
  79.             self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014
  80.         elif csd[0] & 0xc0 == 0x00: # CSD version 1.0 (old, <=2GB)
  81.             c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4
  82.             c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7
  83.             self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2))
  84.         else:
  85.             raise OSError("SD card CSD format not supported")
  86.         #print('sectors', self.sectors)

  87.         # CMD16: set block length to 512 bytes
  88.         if self.cmd(16, 512, 0) != 0:
  89.             raise OSError("can't set 512 block size")

  90.         # set to high data rate now that it's initialised
  91.         self.init_spi(1320000)

  92.     def init_card_v1(self):
  93.         for i in range(_CMD_TIMEOUT):
  94.             self.cmd(55, 0, 0)
  95.             if self.cmd(41, 0, 0) == 0:
  96.                 self.cdv = 512
  97.                 #print("[SDCard] v1 card")
  98.                 return
  99.         raise OSError("timeout waiting for v1 card")

  100.     def init_card_v2(self):
  101.         for i in range(_CMD_TIMEOUT):
  102.             time.sleep_ms(50)
  103.             self.cmd(58, 0, 0, 4)
  104.             self.cmd(55, 0, 0)
  105.             if self.cmd(41, 0x40000000, 0) == 0:
  106.                 self.cmd(58, 0, 0, 4)
  107.                 self.cdv = 1
  108.                 #print("[SDCard] v2 card")
  109.                 return
  110.         raise OSError("timeout waiting for v2 card")

  111.     def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
  112.         self.cs(0)

  113.         # create and send the command
  114.         buf = self.cmdbuf
  115.         buf[0] = 0x40 | cmd
  116.         buf[1] = arg >> 24
  117.         buf[2] = arg >> 16
  118.         buf[3] = arg >> 8
  119.         buf[4] = arg
  120.         buf[5] = crc
  121.         self.spi.write(buf)

  122.         if skip1:
  123.             self.spi.readinto(self.tokenbuf, 0xff)

  124.         # wait for the response (response[7] == 0)
  125.         for i in range(_CMD_TIMEOUT):
  126.             self.spi.readinto(self.tokenbuf, 0xff)
  127.             response = self.tokenbuf[0]
  128.             if not (response & 0x80):
  129.                 # this could be a big-endian integer that we are getting here
  130.                 for j in range(final):
  131.                     self.spi.write(b'\xff')
  132.                 if release:
  133.                     self.cs(1)
  134.                     self.spi.write(b'\xff')
  135.                 return response

  136.         # timeout
  137.         self.cs(1)
  138.         self.spi.write(b'\xff')
  139.         return -1

  140.     def readinto(self, buf):
  141.         self.cs(0)

  142.         # read until start byte (0xff)
  143.         while True:
  144.             self.spi.readinto(self.tokenbuf, 0xff)
  145.             if self.tokenbuf[0] == 0xfe:
  146.                 break

  147.         # read data
  148.         mv = self.dummybuf_memoryview
  149.         if len(buf) != len(mv):
  150.             mv = mv[:len(buf)]
  151.         self.spi.write_readinto(mv, buf)

  152.         # read checksum
  153.         self.spi.write(b'\xff')
  154.         self.spi.write(b'\xff')

  155.         self.cs(1)
  156.         self.spi.write(b'\xff')

  157.     def write(self, token, buf):
  158.         self.cs(0)

  159.         # send: start of block, data, checksum
  160.         self.spi.read(1, token)
  161.         self.spi.write(buf)
  162.         self.spi.write(b'\xff')
  163.         self.spi.write(b'\xff')

  164.         # check the response
  165.         if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
  166.             self.cs(1)
  167.             self.spi.write(b'\xff')
  168.             return

  169.         # wait for write to finish
  170.         while self.spi.read(1, 0xff)[0] == 0:
  171.             pass

  172.         self.cs(1)
  173.         self.spi.write(b'\xff')

  174.     def write_token(self, token):
  175.         self.cs(0)
  176.         self.spi.read(1, token)
  177.         self.spi.write(b'\xff')
  178.         # wait for write to finish
  179.         while self.spi.read(1, 0xff)[0] == 0x00:
  180.             pass

  181.         self.cs(1)
  182.         self.spi.write(b'\xff')

  183.     def count(self):
  184.         return self.sectors

  185.     def readblocks(self, block_num, buf):
  186.         nblocks = len(buf) // 512
  187.         assert nblocks and not len(buf) % 512, 'Buffer length is invalid'
  188.         if nblocks == 1:
  189.             # CMD17: set read address for single block
  190.             if self.cmd(17, block_num * self.cdv, 0) != 0:
  191.                 raise OSError(5) # EIO
  192.             # receive the data
  193.             self.readinto(buf)
  194.         else:
  195.             # CMD18: set read address for multiple blocks
  196.             if self.cmd(18, block_num * self.cdv, 0) != 0:
  197.                 raise OSError(5) # EIO
  198.             offset = 0
  199.             mv = memoryview(buf)
  200. ……………………

  201. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
sdcard.zip (2.41 KB, 下載次數: 24)
0.jpg
回復

使用道具 舉報

ID:415979 發表于 2019-4-5 01:38 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美性生活视频 | 自拍偷拍亚洲一区 | 成人在线观看亚洲 | 精品蜜桃一区二区三区 | 欧美毛片免费观看 | 一区影院| 99久久中文字幕三级久久日本 | 九色 在线 | 一区二区三区四区五区在线视频 | 亚洲精品久久久久久下一站 | 精品国产乱码久久久久久果冻传媒 | av中文字幕在线观看 | 中文在线视频观看 | 在线a视频 | 在线观看国产www | 伊人激情网 | 青青久久av北条麻妃海外网 | 亚洲国产精品福利 | 成人影| 国产日韩中文字幕 | 99精品免费视频 | 密乳av| 欧美国产视频 | 亚洲视频在线看 | 久久中文字幕视频 | av特级毛片 | 一区二区精品 | 久久久久久久亚洲精品 | 久久国产一区 | 伊人性伊人情综合网 | 日日夜夜影院 | 中文字幕av一区 | 日韩av第一页 | av在线免费观看网址 | 二区三区在线观看 | 日韩一级| 国产精品久久久久久久免费观看 | 亚洲一区二区在线视频 | 欧美日韩免费一区二区三区 | 欧美日韩精品久久久免费观看 | 亚洲播放一区 |