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

极术社区 2022-01-07 11:11:16

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

推荐阅读

全志XR806芯片FAQ汇总

...全文
719 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究(Matlab代码实现)内容概要:本文详细介绍了非线性值迭代自适应动态规划(ADP)在离散时间非线性系统中的应用,重点研究了策略迭代自适应动态规划算法的设计与实现。文章通过构建数学模型,结合Matlab代码实现了对非线性系统的控制策略优化,分析了算法在不同工况下的性能表现,并探讨了其在工程实践中的可行性和有效性。研究涵盖了系统建模、控制器设计、仿真验证等关键环节,旨在为复杂非线性系统的自动化控制提供新的解决方案。; 适合人群:具备一定编程基础和控制系统理论知识的科研人员或工程师,特别是从事自动化、人工智能、智能控制等相关领域的研究人员。; 使用场景及目标:①为非线性系统的控制问题提供有效的数值求解方法;②通过Matlab编程实践加深对自适应动态规划算法的理解;③推动ADP算法在工业自动化、机器人控制、智能制造等领域的应用研究; 阅读建议:建议读者结合Matlab软件进行代码复现,深入理解算法细节,并尝试将其应用于其他类型的非线性系统中,以检验算法的普适性和鲁棒性。同时,鼓励查阅相关文献,进一步拓展对该领域前沿技术的认识。
内容概要:本文研究了基于粒子群算法(PSO)优化K-means聚类的居民用电行为分析方法,并提供了完整的Matlab代码实现。针对传统K-means算法对初始聚类中心敏感、易陷入局部最优的问题,引入粒子群算法进行优化,利用PSO的全局搜索能力来寻找更优的初始聚类中心,从而提升聚类的准确性和稳定性。研究以居民用电数据为对象,通过PSO-Kmeans方法对用户的用电模式进行分类,旨在更精确地识别不同类型的用电行为,为电力公司的精准营销、需求侧管理和个性化服务提供数据支持。文中详细阐述了算法的实现流程,并通过仿真实验验证了该方法相较于传统K-means的有效性。; 适合人群:具备一定数据分析和机器学习基础,对智能优化算法和电力系统数据分析感兴趣的科研人员、研究生及电力行业从业者。; 使用场景及目标:①应用于居民用电行为的精准分类与模式识别;②解决传统聚类算法初始值敏感和局部收敛问题,提升电力大数据分析的准确性;③为电力需求侧管理、负荷预测和制定差异化电价策略提供技术支持。; 阅读建议:此资源结合了理论算法与Matlab代码实现,建议读者在理解PSO和K-means算法基本原理的基础上,动手实践所提供的代码,通过调整参数和分析运行结果来深入掌握该混合优化算法在实际数据处理中的应用效果。

31,523

社区成员

发帖
与我相关
我的任务
社区描述
欢迎加入极术社区,共创中国智能计算生态。社区提供智能计算领域的资讯,鼓励技术写作和问答互助,致力促进中国芯片技术的合作创新。地址:https://aijishu.com
人工智能 企业社区
社区管理员
  • 极术社区
  • 闫辉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧