18

甴尐 · 2022年01月06日

【XR806开发板试用】简单点灯-- 基于SPI控制W2812矩阵幻彩动图和字幕显示系统

1.效果展示

1.gif 动图展示

2.gif

2.字幕展示

1 (2).gif

2.软件开发流程

2.1 全志XR806 基本开发流程

使用指南
自己踩过的坑
image.png
必须app开头
鸿蒙hb 依赖python 环境。建议使用conda虚拟环境
image.png
下载开启硬件校验和烧录重启

2.2 W2812 简单介绍

不是科普文,自行百度
`/*WS2812B Timing sequence

    ________
   |        |       T0L         |

0 code |<------>|<-------------->|

   |  T0H   |________________|
   
   
    ___________
   |           |       T1L      |

1 code |<--------->|<--------- -->|

   |  T1H      |______________|   
   
   

RET code

   |         Treset                |
   |<------------------------->|
   |___________________________| 
   

Data transefer time:
T0H 0 code ,high voltage time 0.4us ±150ns
T1H 1 code ,high voltage time 0.8us ±150ns
T0L 0 code , low voltage time 0.85us ±150ns
T1L 1 code ,low voltage time 0.45us ±150ns
RES low voltage time Above 50us

*/`

硬件驱动

供电 5V
驱动电平 gpio口3.3v 需要加一些简单的转换电路到5v
驱动时序 这里使用SPI 驱动 支持DMA搬运
image.png
PB04 SPIO_MOSI 引脚
image.png

2.3 软件框架

2.3.1 UDP

1.联网获取IP
使用 wlan_demo 中 例子 wifi_device_connect_test
2.绑定端口
`void udp_echoserver_init(void)
{

struct udp_pcb *upcb;
err_t err;
/* Create a new UDP control block  */
upcb = udp_new();
if (upcb)
{
    /* Bind the upcb to the UDP_PORT port */
    /* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
    err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
    if (err == ERR_OK)
    {
        /* Set a receive callback for the upcb */
        udp_recv(upcb, udp_server_receive_callback, NULL);
        printf("led udp bind OK \r\n");
    }else    
        printf("led udp bind error \r\n");
}

}
`
3.注册接收回调
`void udp_server_receive_callback(void arg, struct udp_pcb upcb,struct pbuf p, const ip_addr_t addr, u16_t port)
{

printf(" 11 udp receive_callback \r\n");
/* Connect to the remote client */
udp_connect(upcb, addr, port);
/* Tell the client that we have accepted it */
udp_send(upcb, p);
memset(udp_recv_date,0x00,UDP_RECV_DATE_MAX);
uint32_t buf_len = pbuf_copy_partial(p, udp_recv_date, p->len, 42); 
uint32_t cur_pos;
if(UDP_RECV_LED_BUFF_LEN==buf_len){
    #if 1
    for(u32_t i = 0;i < buf_len;){
        if(i%48==0)printf("\r\n");
        printf("%x-%x-%x ",udp_recv_date[i],udp_recv_date[i+1],udp_recv_date[i+2]);
        if(udp_recv_date[i]!=0)cur_pos = i;
        i+=3;
    }
    printf("\r\n recv data %d,pos=%d  %d,%d\r\n",buf_len,cur_pos,cur_pos/48,(cur_pos%48)/3);
    #endif
    led_spi_update(udp_recv_date);
    //led_spi_update_test();
}
/* free the UDP connection, so we can accept new clients */
udp_disconnect(upcb);
/* Free the p buffer */
pbuf_free(p);

}`
4.提取UDP数据
pbuf_copy_partial(p, udp_recv_date, p->len, 42);
这里偏移了42。包含了一些UDP通信的信息。

2.3.2 SPI 驱动

1.SPI初始化 这里使用6M的速率
`void led_spi_init(void)
{

  printf("led_spi_init\r\n");
  IoTGpioInit(GPIO_ID_PA21);                                                    //(3)
  IoTGpioSetDir(GPIO_ID_PA21, IOT_GPIO_DIR_OUT);                                //(4)

uint16_t i = 0;
uint16_t loop_color = 0;
SPI_Global_Config spi_param;

spi_param.cs_level = DEMO_SPI_CS_LEVEL;
spi_param.mclk = DEMO_SPI_MCLK;

HAL_SPI_Init(DEMO_SPI_PORT, &spi_param);


SPI_Config spi_Config;
HAL_Status ret = HAL_OK;

spi_Config.firstBit = SPI_TCTRL_FBS_MSB;
spi_Config.mode = SPI_CTRL_MODE_MASTER;
spi_Config.opMode = SPI_OPERATION_MODE_DMA;
spi_Config.sclk = DEMO_SPI_MCLK;
spi_Config.sclkMode = SPI_SCLK_Mode1;

printf("spi open...\n");
ret = HAL_SPI_Open(DEMO_SPI_PORT, DEMO_SPI_CS, &spi_Config, 5000);
if (ret != HAL_OK) {
    printf("spi open failed");
    return ret;
}
HAL_SPI_Config(DEMO_SPI_PORT, SPI_ATTRIBUTION_IO_MODE, SPI_IO_MODE_NORMAL);
printf("led_spi_init ok.\n");

}
`
2.数据发送
HAL_SPI_Transmit
这里有坑:SPI驱动第一次数据第一个自己前2位。波形离谱。这里通过多发一个字节0x00.避免过去。

点阵屏

点阵屏灯排布

image.png
这里需要根据自己的走向修改程序。
`void broad_ws2812_set_position(uint8_t w,uint8_t h,uint8_t r,uint8_t g,uint8_t b)
{

uint16_t pos = 0;
pos = w*BROAD_WS2812_STRIP_LED_H;
if(w%2==0){
    pos +=h;
}
else{
    pos +=(BROAD_WS2812_STRIP_LED_H-h-1);
}
if(r==g&&r==b)
{
    led_spi_buff[pos*3+0] = 0;          //
    led_spi_buff[pos*3+1] = 0;
    led_spi_buff[pos*3+2] = 0;
}
else{
    led_spi_buff[pos*3+0] = b/2;          //
    led_spi_buff[pos*3+1] = r/2;
    led_spi_buff[pos*3+2] = g/2;
}

}`

把2812控制数据变化成SPI数据

`static void led_data_to_ws2812(uint8_t val, uint8_t* dst)
{

int i = 7;

for (i = 7; i >= 0; i--)
{
    if ((val >> i) & 0x01)
    {
        *(dst++) = 0xfc;
    }
    else
    {
        *(dst++) = 0xc0;
    }
}

}`

系统简介

本系统实现了,使用python 控制 wifi蓝牙 2812点阵板子控制。可以实现大数据传输,实时仿真控制,暂时很好效果。

开源 百度网盘大家自行下载测试

image.png
链接:https://pan.baidu.com/s/1b3u0...
提取码:6666

推荐阅读
关注数
13823
内容数
139
全志XR806开发板相关的知识介绍以及应用专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息