单片机的第一道难关无疑是烧录,如果烧录解决了,那么就有资格挑战各种坑了。
BK7251播放MP3
一、折腾材料
1、软件SDK:
bk7251_audio_release_20190826_0701(BK7251 rtt sdk),可以从github,gitee,淘宝(麻雀一号的资料包)中获得。
2、硬件材料:
1、正面和反面
2、折腾全家福
3、特写
BK7251本尊
转接板,将电源、SPI烧写口、串口2引出了。
串口工具
CH341,用SPI烧写和GPIO。
再来一张BK7251特写还是挺帅的,旁边的小兄弟LTK8002D 是一个3w的功放,后面要提到它。
二、资料收集
BK7251:
BK7251的引脚图,因为要播放音乐,需重点关注以下引脚:其中AUDRP和AUDRN是右声道输出正极和负极。AUDLP和AUDLN是左声道输出正极和负极。
LTK8002D:
三、开始
1、用到的资料和工具比较多,特意建了个文件夹放连接
2、编译:进到BK7251 根目录,点右键菜单中的conEmu Here,打开rt_thread env环境。
键入scons编译,我这里之前编译过,所以输出比较少。
3、用beken_packager打包bin
beken_packager是rt_thread为beken开发的打包工具。用于将bootloader、编译的app和其他的用户数据bin打包在一起用于烧录。
进入:bk7221u_release\tool\beken_packager。
其中,config_audio_4M_ROMFS.json的内容,这个文件描述了要打包文件的信息:
1、bootloader_7251_4M_ROMFS_uart2_20181220.bin是bootloader;
2、../../rtthread.bin是前面编译的app bin;
3、romfs_root.bin是数据bin,这个以后再说。
config_audio_4M_ROMFS.json:
{
"magic": "RT-Thread",
"version": "0.1",
"count": 2,
"section": [
{
"firmware": "bootloader_7251_4M_ROMFS_uart2_20181220.bin",
"version": "4M.1220",
"partition": "bootloader",
"start_addr": "0x00000000",
"size": "65280"
},
{
"firmware": "../../rtthread.bin",
"version": "4M_ROMFS.1220",
"partition": "app",
"start_addr": "0x00011000",
"size": "2244K"
},
{
"firmware": "romfs_root.bin",
"version": "4M_ROMFS.1220",
"partition": "romfs",
"start_addr": "0x00242000",
"size": "544K"
}
]
}
操作:将config_audio_4M_ROMFS.json拖到beken_packager.bat文件上,进行打包。生成结果all_4M_ROMFS.1220.bin
4、烧录
1、接上CH341,用SPI使能烧录
使能原理请参见:CH341 SPI方式烧录BK7231U-CSDN博客
运行这个python程序使能烧录
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):
#dout = bytearray(250)
#print("input data:",hex(data))
#print('\r\n')
send_buf = bytearray(25)
#print("Send 250 '",hex(data),"'\r\n")
for x in range(25):
send_buf[x] = data
send_buf=hd.ch341_spi4w_stream(bytes(send_buf))
for x in range(25):
send_buf[x] = 0x00
send_buf=hd.ch341_spi4w_stream(bytes(send_buf))
for x in range(0,25):
print(send_buf[x],end = " ")
#print(hex(dout[x]),end = " ")
print('\r\n')
if(send_buf[x]==b'\xd2'):
return 1
#print('\r\n')
#print('---------------- test 1 0x9F-----------------------\r\n')
###
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
for x in range(4):
#print(hex(buf1[x]), end = ' \r\n')
print(hex(buf1.raw[x]), end = ' ')
#print(buf1.raw)
print('\r\n')
#buf1[0]=0x00
#buf1[1]=0x00
#buf1[2]=0x00
#buf1[3]=0x00
#buf1=hd.ch341_spi4w_stream(bytes(buf1))
#print(buf1.raw)
print('\r\n')
#print('\r\n---------------- test 1 over -----------------------\r\n')
if out1!=b'\x00' and zeroCount==3:
return 1
return 0
###
def ReadStart(startaddr, filename, readlen):
count = 0
addr = startaddr
f = open(filename, "wb")
size = readlen
size = (size+255)//256*256
print("Reading")
while count < size:
print("count "+str(count) +"/"+str(size))
send_buf = bytearray(4+256)
send_buf[0] = 0x03
send_buf[1] = (addr & 0xFF0000) >> 16
send_buf[2] = (addr & 0xFF00) >> 8
send_buf[3] = addr & 0xFF
#result = spi.xfer2(send_buf)
result=hd.ch341_spi4w_stream(bytes(send_buf))
count += 256
addr += 256
#part = bytearray(result[4:4+256])
part = bytearray(result[4:4+256])
for x in range(256):
print(hex(part[x]), end = '')
print(" ", end = '')
f.write(part)
f.close()
ChipReset()
return True
hd = CH341DEV(0)
#hd.ch341_i2c_speed(3)
#ChipReset()
#ReadStart(0,"text.bin",0x11000)
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")
buf1 = bytearray(4)
buf1=b'\x9F\x00\x00\x00'
buf1=hd.ch341_spi4w_stream(bytes(buf1))
buf1=b'\x00\x00\x00\x00'
buf1=hd.ch341_spi4w_stream(bytes(buf1))
for x in range(4):
print(buf1[x],end=" ")
break
#print('\r\n.............................................................\r\n')
time.sleep(1)
if ifEnterSpiMode!=1:
print("Enter SpiMode failure!!! let's run againt \r\n")
结果:
2、然后用NeoProgrammer.exe烧录
操作步骤:打开要烧录的文件,上面的all_4M_ROMFS.1220.bin,点击第5个按键烧录。
5、接上喇叭和串口工具
打开SecureCRT.exe 工具,上电如果正常可以看到:
6、试验
1、help
2、wifi w0 join xxx xxx
接入AP
3、ifconfig
4、cd romfs
5、player gyz.mp3
播放MP3
命令发送正常,player status查看状态也对,但就是没有声音输出。
后来发现LTK8002D的1引脚shutdown在player命令发出后一直处于高电位,而shutdown需要低电位才能播放。
shutdown接到了BK7231的GPIO9,所以就想把GPIO9设置为低电平就应该有输出
利用一下sdk中GPIO sample例程。在GPIO_sample.c中修改:
#define LED0 9 //30
void led_thread_entry(void *parameter)
{
rt_pin_mode(LED0, PIN_MODE_OUTPUT);
rt_pin_write(LED0, PIN_LOW);
// while (1)
// {
// rt_pin_write(LED0, PIN_LOW);
// rt_thread_delay(rt_tick_from_millisecond(500));
// rt_pin_write(LED0, PIN_HIGH);
// rt_thread_delay(rt_tick_from_millisecond(500));
// }
}
这样调用gpio这个例程就可以使shutdown设为低电平。
env环境键入:menuconfIg,使能 gpio sample
重新scons编译,然后打包,下载。
6、再次执行player、再执行gpio
有声音了
7、播放WEB server上的mp3
建了个WEB SERVER
WEB SERVER根目录下放了几个MP3
键入:player http://192.168.8.11/xing.mp3
键入:gpio
音量调小点:player volume 10
停止: player stop
四、总结
1、BK7231、BK7251、BK7252是一个系列的芯片,都有RT_THREAD SDK,开发需要了解一些RT_THREAD的知识。
2、RT_THREAD是一个rtos操作系统,操作系统有分区就不奇怪了,而分区是存在bootloader中的,官方提供了一个rt_partition_tool.exe的工具,可以查看和修改分区。下面就是bootloader_7251_4M_ROMFS_uart2_20181220.bin分区情况,这个分区对beken_packager打包是有用的,需要对应上。app是SDK应用分区;romfs是数据分区(可没有);dowload是OTA升级用分区。
3、romfs_root.bin可以包括一些数据信息如MP3,SDK中有文档说明如何生成,要注意和分区信息对应上。
也可用OTA方式将romfs_root.bin传上去,OTA打包工具选择不加密,固件分区名:filesystem。生成romfs_root.rbl,放到web server根目录下,用http_ota http://xx.xx.xx.xx/romfs_root.rbl传上去。