Skip to content

由 WildboarG 贡献,Ai-Thinker 进行整理

Ai-WB2的SPI测试

WB2 SPI测试


关于hosal库


测试wb2的spi发现一直溢出,用的是 WB2-12Fkit开发板,跑园长的demo点亮ws2812卡在了spi初始化,发现论坛也有大佬卡在了初始化.

使用printf大法一点点跟踪,发现具体卡在了GPIO的初始化这个函数

📜 点击展开完整代码
c
static

void

hosal_spi_gpio_init
(
hosal_spi_dev_t
 *arg)

{

if
 (!arg) {
        blog_error(
"arg err.\r\n"
);

return
;
    }

    GLB_GPIOgeng huan_Type gpiopins[
4
];
    gpiopins[
0
] =
22
;
//这里注释掉就可以初始化完成

    gpiopins[
1
] = arg->config.pin_clk;
    gpiopins[
2
] = arg->config.pin_mosi;
    gpiopins[
3
] = arg->config.pin_miso;
    GLB_GPIO_Func_Init(GPIO_FUN_SPI,gpiopins,
sizeof
(gpiopins)/
sizeof
(gpiopins[
0
]));

if
 (arg->config.mode ==
0
) {
        GLB_Set_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_MASTER);
    }
else
 {
        GLB_Set_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_SLAVE);
    }

return
;
}

不明白为什么将SPI的GPIO除了用到的引脚还初始化22号引脚,看手册上12F不能用这个引脚,把它给注释掉了,然后只初始化CLK MOSI MISO这三个引脚,然后就能正常完初始化.但是发送数据依旧报溢出的问题.

不死心,自己写一个spi发送的demo依然溢出.

更换SDK

折腾了两天解决不了,然后尝试换博流的SDK,看文档说对bl602/bl604支持SPI但未测试,心凉一半. 写了发送1234...的demo用编译烧录,又又出错了,再次搬出printf大法跟踪,定位到 board.c 文件的这里

📜 点击展开完整代码
c
void

board_spi0_gpio_init
()

{

// struct bflb_device_s *gpio;

// gpio = bflb_device_get_by_name("gpio");

// bflb_gpio_init(gpio, GPIO_PIN_18, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

// bflb_gpio_init(gpio, GPIO_PIN_19, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

// bflb_gpio_init(gpio, GPIO_PIN_20, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);

}

使用SPI的引脚引脚需要自己实现初始化(它这里给注释掉了,表示需要按照实际的引脚来用).

查手册,看支持的SPI引脚不少,选了IO3 IO4 IO5

再次烧录测试,能够成功发送数据,接受方也表示没毛病.

但是神奇的事情发生了,再次用 Ai-Thinker-WB2sdk烧录程序,怎么都烧录不进去,用 bouffalo的sdk就可以正常烧录,有大佬知道这是什么原因吗?

然后尝试点亮WS2812灯珠的示例:

📜 点击展开完整代码
c
#
include

"bflb_mtimer.h"

#
include

"bflb_spi.h"

#
include

"board.h"

#
include

"bflb_gpio.h"

#
include

<stdio.h>

#
define
 SPI_MASTER_CASE    0

#
define
 SPI_SLAVE_CASE     1

#
define
 SPI_CASE_SELECT    SPI_MASTER_CASE

// SPI数据为0的时序

#
define
 SPI_NEO0           ((uint8_t)0b11000000)

// SPI数据为1的时序

#
define
 SPI_NEO1           ((uint8_t)0b11111100)

#
define
 BITS_PER_LED_COLOR (sizeof(color_t) * 8)

#
define
 BUFF_LEN           (8 * 1024)

uint32_t
 tx_buff[BUFF_LEN /
4
];

uint32_t
 rx_buff[BUFF_LEN /
4
];

struct

bflb_device_s
 *
spi0
;

typedef

struct
 {

uint8_t
 r;

uint8_t
 g;

uint8_t
 b;
}
color_t
;

typedef

struct
 {

uint16_t
 led_counts;
// LED数量

uint8_t
 *color_datas;
// 24位颜色数据

uint16_t
 color_data_size;
// 颜色数据长度

color_t
 *led_colors;
// LED颜色

bool
 inited;
// 是否初始化,1表示已经初始化,0则表示未初始化

}
ws2812b_t
;

ws2812b_t
 ws2812b = {
    .inited =
false
,
    .led_counts =
1
,
};

color_t
 RED = {
255
,
0
,
0
 };

color_t
 GREEN = {
0
,
255
,
0
 };

color_t
 BLUE = {
0
,
0
,
255
 };

void

ws2812b_init
(
ws2812b_t
 *ws2812b)

{

if
 (ws2812b ==
NULL
) {

return
;
    }

// 分配24位颜色数据内存

    ws2812b->color_datas = (
uint8_t
 *)
malloc
(
        ws2812b->led_counts * BITS_PER_LED_COLOR +
32
);

// 分配LED颜色数据内存

    ws2812b->led_colors = (
color_t
 *)
malloc
(

sizeof
(
color_t
) * ws2812b->led_counts);

if
 (ws2812b->color_datas && ws2812b->led_colors) {
        ws2812b->inited =
true
;
        ws2812b->color_data_size = ws2812b->led_counts * BITS_PER_LED_COLOR;
//+32

    }
else
 {
        ws2812b->inited =
false
;
    }
}

// 生成24位颜色数据序列

void
 __build_led_color_data(
ws2812b_t
 *ws2812b)
{

for
 (
int
 i =
0
; i < ws2812b->led_counts; i++) {

uint8_t
 m =
0b10000000
;

for
 (
int
 b =
0
; b <
8
; b++) {
            ws2812b->color_datas[BITS_PER_LED_COLOR * i + b] =
                ws2812b->led_colors[i].g & m ? SPI_NEO1 : SPI_NEO0;
            m >>=
1u
;
        }

        m =
0b10000000
;

for
 (
int
 b =
0
; b <
8
; b++) {
            ws2812b->color_datas[BITS_PER_LED_COLOR * i + b +
8
] =
                ws2812b->led_colors[i].r & m ? SPI_NEO1 : SPI_NEO0;
            m >>=
1u
;
        }

        m =
0b10000000
;

for
 (
int
 b =
0
; b <
8
; b++) {
            ws2812b->color_datas[BITS_PER_LED_COLOR * i + b +
16
] =
                ws2812b->led_colors[i].b & m ? SPI_NEO1 : SPI_NEO0;
            m >>=
1u
;
        }
    }
}

void

ws2812b_set_color
(
ws2812b_t
 *ws2812b,
uint16_t
 index,
color_t
 color)

{

if
 (index >= ws2812b->led_counts && ws2812b->inited) {

return
;
    }
    ws2812b->led_colors[index] = color;
}

void

ws2812b_show
(
ws2812b_t
 *ws2812b)

{

if
 (!ws2812b->inited) {

return
;
    }
    __build_led_color_data(ws2812b);

//hosal_spi_send(&spi, ws2812b->color_datas,ws2812b->color_data_size,1000);

printf
(
"countsize=%d\r\n"
, ws2812b->color_data_size);

for
 (
int
 i =
0
; i < ws2812b->color_data_size; i++) {
        bflb_spi_poll_send(spi0, ws2812b->color_datas[i]);
    }
}

void

board_spi0_gpiomy_init
()

{

struct

bflb_device_s
 *
gpio
;

    gpio = bflb_device_get_by_name(
"gpio"
);
    bflb_gpio_init(gpio, GPIO_PIN_3, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_4, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_5, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
}

/* poll test func */

/* main */

int

main
(
void
)

{
    board_init();
    board_spi0_gpiomy_init();

struct

bflb_spi_config_s

spi_cfg
 =
 {

#
if
 (SPI_CASE_SELECT == SPI_MASTER_CASE)

        .freq =
8
 *
1000
 *
1000
,
        .role = SPI_ROLE_MASTER,

#
else

        .freq =
32
 *
1000
 *
1000
,
        .role = SPI_ROLE_SLAVE,

#
endif

        .mode = SPI_MODE3,
        .data_width = SPI_DATA_WIDTH_8BIT,
        .bit_order = SPI_BIT_MSB,
        .byte_order = SPI_BYTE_LSB,
        .tx_fifo_threshold =
0
,
        .rx_fifo_threshold =
0
,
    };

    spi0 = bflb_device_get_by_name(
"spi0"
);
    bflb_spi_init(spi0, &spi_cfg);

//uint32_t mess = 0;

printf
(
"start\r\n"
);

// bflb_spi_poll_send(spi0, mess);

    ws2812b_init(&ws2812b);

printf
(
"ws2812b task start...\r\n"
);

while
 (
1
) {

//      bflb_mtimer_delay_ms(2000); /* delay for slave device prepare ok */

//      bflb_spi_poll_send(spi0, mess);

//      mess++;

for
 (
size_t
 i =
0
; i < ws2812b.led_counts; i++) {
            ws2812b_set_color(&ws2812b, i, RED);
        }
        ws2812b_show(&ws2812b);

        bflb_mtimer_delay_ms(
1000
);

for
 (
size_t
 i =
0
; i < ws2812b.led_counts; i++) {
            ws2812b_set_color(&ws2812b, i, GREEN);
        }
        ws2812b_show(&ws2812b);

        bflb_mtimer_delay_ms(
1000
);

for
 (
size_t
 i =
0
; i < ws2812b.led_counts; i++) {
            ws2812b_set_color(&ws2812b, i, BLUE);
        }
        ws2812b_show(&ws2812b);

        bflb_mtimer_delay_ms(
1000
);
    }
}

编译烧录

📜 点击展开:make CHIP=BL602 BOARD=bl602dk
shell
make CHIP=BL602  BOARD=bl602dk
📜 点击展开:make flash CHIP=BL602 COMX=/d
shell
make flash CHIP=BL602  COMX=/dev/ttyUSB0

嘿,你猜怎么着,WB2-12F-kit上边的灯珠颗RGB5050灯珠,用单线协议没用,直接用高低电平控制的,只能用用逻辑分析仪检测一下控制逻辑是否正确.

已经解析出来WS2812协议了

ok

其他


其实我之前画过WB2-12f的测试版,要驱动IIC用的,上边刚好有一颗WS2812灯珠接在io5上.想把上边程序下载上去验证,但一直无法烧录(用 Ai-Thinker-WB2SDK就可以正常烧录程序),简直是倒反天罡.我就说水逆吧.

还有个问题,我没明白博流sdk 的spi如何为功能引脚指定GPIO引脚.求评论区大佬解答.

Released under the MIT License. Build Time 2026-09-11 14:52:23