CH341 SPI方式烧录BK7231U

        a33068f2f60ed7cc4bbbbc6f84f72e39.pngCH341是一个USB总线的转接芯片,通过USB总线提供异步串口、打印口、并口以及常用的2线和4线等同步串行接口。

        f76db1aef4fa0123146a1b6e7c3f3553.png BK7231U Wi-Fi SOC芯片,内嵌处理器。1. 符合802.11b/g/n 1x1协议    2. 17dBm 输出功率3. 支持20/40 MHz带宽和STBC    4. 支持Wi-Fi STA、AP、Direct模式 5. 支持蓝牙5.1协议,-90dB灵敏度和20dBm输出功率    6. 片内MCU 7. 最高频率120MHz    8. 片内256Kbyte数据RAM 9. 内置2MB FLASH,支持透明下载    10. 6路32位 PWM 11. 多路程序下载与JTAG接口    12. 全速USB主机和设备 13. 50MHz SDIO和SPI接口,并支持主从模式    14. 支持两路I2C接口
15. 支持两路高速UART   16. 6路32位PWM 17. 麦克风信号放大    18. 内置多通道ADC 19. 支持8位DVP 图像传感器    20. 32字节eFUSE

        BEKEN(博通集成)的芯片还是不错的,比如这款BK7231U是对标ESP8266的,并且还有蓝牙功能。但是官方的通用烧写器,价格大约200多,对爱好者来说毫无性价比可言。并且BEKEN的官网什么都没有,数据手册、SDK这些都是给企业用户。个人用户想学习难度不小。

        直到看了这篇https://www.elektroda.com/rtvforum/topic3931424.html用python+ Raspberry Pi实现了对BK7231的烧写。感觉还有点搞头。

        手头没有Raspberry Pi,照搬原作者的方法不太现实。所以做了下变通,就有了后面的方法:

一、硬件连接

7b7b8d9cfcce42e787fa4552a43eee20.jpeg

        这个C-8133U模块主控是BK7231U,没有模块资料,模块引脚定义是自己测的。

        下面是BK7231U芯片的引脚定义,注意和其他的BK7231,比如BK7231T、BK7231N是不一样的。

ea4c4c37033d4c679745587550a7e4d6.png

        左边是BK7231U,右边是CH341

GND  <------------------->  GND

VBAT/3V3    <---------->   VCC

CEN         <-------------->  D2(GPIO)

P23/MOSI <------------->  MISO

P22/MISO <-------------->  MOSI

P21/CSN <-----------------> CS0

P20/SCK <----------- -----> SCK

a096b6f8e12942bb9d19797877430826.png

二、烧录原理

        BK7231U中存储用户程序的flash是一个25系列的flash,支持SPI读写。但是直接用CH341读写BK7231u是不行的。BK7231U数据手册中关于程序下载有如下描述:2ce9551e58814bfe8b5c880d60ac63e8.png

         也就是说,需要在芯片复位后做模式选择使CH341将BK7231U当作一个flash,如果错过了复位后的几百毫秒,BK7231U进入MCU运行模式,就不能烧录的。

三、烧录实现

1、使BK7231U进入SPI烧录模式

import random
import time
import numpy as np
from matplotlib import pyplot as plt
import os
import random
import numpy as np
from fractions import Fraction
import pyautogui
from PIL import Image
import binascii
import struct
import codecs
import binascii


## call ch341dll_wrap
from ch341dll_32bits_wrap.ch341dll_wrap  import *

#CEN:GPIO02
#
#
def GPIO_CEN_SET():
	result=ch341dll.CH341Set_D5_D0(hd.usb_id,0x04,0x04)
	if result==1:
		print("Set CEN hight success!\r\n")
def GPIO_CEN_CLR():
	result=ch341dll.CH341Set_D5_D0(hd.usb_id,0x04,0x00)
	if result==1:
		print("Set CEN low success!")

def ChipReset():
    # set CEN low for 1s
    GPIO_CEN_CLR()
    time.sleep(0.1)
    GPIO_CEN_SET()

def BK_EnterSPIMode(data):
	send_buf = bytearray(25)

	for x in range(25):
		send_buf[x] = data
	send_buf=hd.ch341_spi4w_stream(bytes(send_buf))

	buf1 = bytearray(4)
	buf1[0]=0x9F
	buf1[1]=0x00
	buf1[2]=0x00
	buf1[3]=0x00
	#buf1=b'\x9F\x00\x00\x00'
	
	buf1=hd.ch341_spi4w_stream(bytes(buf1))
	out1=buf1[0]
	zeroCount=0;
	for x in range(1,4):
		if(buf1[x]==b'\x00'):
			zeroCount+=1
	print(buf1.raw)

	if out1!=b'\x00' and zeroCount==3:
		return 1
	return 0



	
hd = CH341DEV(0)
hd.ch341_i2c_speed(3)

for x in range(1,11):
    print('\r\n\r\n\r\n----------------try into BK_SPIMode-----------------------\r\n')
    print("attemp to make BK7321 into SpiMode , the [",x,"] Times\r\n")
    ChipReset()
    ifEnterSpiMode=BK_EnterSPIMode(0xD2)
    if(ifEnterSpiMode==1):
        print("\r\nEnter SpiMode success!!!\r\n")
        break
    time.sleep(1)
	
if ifEnterSpiMode!=1:
    print("Enter SpiMode failure!!!   let's run againt \r\n")	

       这个PYTHON程序向CH341发送25个0xD2(必须是0xD2,发送多少个好像也没有固定的数量要求),然后发送了0x9F查询了一下flash的id。再判断spi接收,好像是0xd2命令应该返回1个0xd2,24个0x00,0x9f命令返回id。但实际上0xd2返回1个非0的数和24个0,0x9f返回0xd2和3个0。这里有点玄学,有几率使BK7231U进入SPI烧录模式。这个方法可靠性不高,所以轮询了10次,总能成功的,不行就再运行一遍。

c05d8a05bc5547028ba21c02a5ff9330.png

2、用NeoProgrammer程序烧录bin到BK7231U

        BK7231U进入SPI烧录模式后,打开NeoProgrammer,BK7231U会被NeoProgrammer识别为GD25Q16。选好要烧录的bin文件(bootloader+用户bin打包文件),直接烧录。

ad58bce6390548fdb4e5cec9593cc4cc.png612f8a35ca1545eb84689ab6d00c82e9.png

四、总结

1、为什么不用PYTHON程序直接把后面下载BIN的步骤都实现了?

        主要是水平有限,只实现了PYTHON使能BK7231U进入SPI模式。

        

2、NeoProgrammer是驱动CH341读写24、25系列FLASH的专用程序,网上比较好找。NeoProgrammer下载flash稳定好用。

3、ch341dll_32bits_wrap.ch341dll_wrap这个依赖可以从这里下载GitHub - jimjiang2/ch341dll_wrap_typical_app: A ch341dll Wrap is for using in Python 32bits windows to access I2C SPI and MDIO (by GPIO), and Demo with display PC sreen on OLED by i2c or SPI .

4、BK7231U有rtt SDK:

GitHub - aozima/bk7231u_rtt_sdk: bk7231u_rtt_sdk

可以通过RTTHREAD env编写自己的固件。生成烧写用的bin,再用bk7231u_rtt_sdk\OTAPackage\beken_packager\beken_packager.exe打包一下,把bootloader打包进去,再用NeoProgrammer烧写。

5、实测对BK7251也有效

        被识别为XT25F32B,4M flash

65f1f5fb93634bf4b76cf89ff6f65cf0.png

12e98d33629e49198d59c6b306d912fd.jpg

585b258131dd4d43a1deb6083234789e.jpg

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
您可以使用Unity的C#脚本来读写CH341芯片的SPI。首先,您需要在Unity中安装CH341的驱动程序,并使用CH341提供的DLL文件来访问芯片。以下是一个简单的示例代码,可以帮助你读写CH341芯片的SPI: ```csharp using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; public class CH341SPI : MonoBehaviour { [DllImport("CH341DLL.dll")] private static extern int CH341OpenDevice(int iIndex); [DllImport("CH341DLL.dll")] private static extern int CH341SetStream(int iIndex, int iMode, int iBaud, int iDelay); [DllImport("CH341DLL.dll")] private static extern int CH341ReadData(int iIndex, byte[] pReadData, int iLength); [DllImport("CH341DLL.dll")] private static extern int CH341WriteData(int iIndex, byte[] pWriteData, int iLength); public string deviceName = "CH341"; public int deviceIndex = 0; public int spiMode = 0; public int spiBaudRate = 500000; public int spiDelay = 0; private int deviceHandle = -1; void Start() { deviceHandle = CH341OpenDevice(deviceIndex); if (deviceHandle < 0) { Debug.LogError(deviceName + " device not found!"); return; } int result = CH341SetStream(deviceHandle, spiMode, spiBaudRate, spiDelay); if (result < 0) { Debug.LogError(deviceName + " set stream error: " + result); } } void OnDestroy() { if (deviceHandle >= 0) { CH341SetStream(deviceHandle, 0, 0, 0); CH341CloseDevice(deviceHandle); } } public byte[] ReadSPI(int length) { byte[] data = new byte[length]; int result = CH341ReadData(deviceHandle, data, length); if (result < 0) { Debug.LogError(deviceName + " read error: " + result); return null; } return data; } public bool WriteSPI(byte[] data) { int result = CH341WriteData(deviceHandle, data, data.Length); if (result < 0) { Debug.LogError(deviceName + " write error: " + result); return false; } return true; } } ``` 您可以将此脚本组件添加到Unity场景中的GameObject上,然后通过调用`ReadSPI`和`WriteSPI`函数来读写CH341芯片的SPI。请注意,在使用此代码之前,您需要将`CH341DLL.dll`文件放置在Unity项目的Assets文件夹中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值