STM32 ws2812b多屏驱动程序

文章目录

  • 前言
  • 一、ws2812b的数据传输以及屏幕的组合
  • 二、代码
    • ws2812screen.c文件
    • ws2812screen.h文件
    • 主函数


前言

在上篇文章中使用了stm32的dma+tim的方式点亮了ws2812b的灯
但是我的需求不仅仅是点亮他,我需要他像屏幕一样显示某一些东西,ws2812显示有一个开源库AWTRIX
这个库需要使用上位机不是很符合我的需求。
所以自己写了一个屏幕的驱动,后续会不断在此基础上改进。
例如我使用的是一个5*5的小ws2812b的屏幕

在这里插入图片描述

但是我需要把多个屏幕组合起来。当点亮某个屏幕的时候不能总是一个个按照他的数据方向一个个数。所以我们就需要对每个灯珠进行重映射–也就是通过【x】【y】的方式来点亮屏幕。
在这里插入图片描述

2023/7/17 可以多块屏幕组合进行显示,可以设置数据流动方向

一、ws2812b的数据传输以及屏幕的组合

ws2812b的数据传输是有方向的以我买的屏幕为例.
绿色的是板子的第一个灯,按照这个数据流向。

在这里插入图片描述
当把多个板子组合在一起的时候
数据就是这样子流向

在这里插入图片描述
再有多行板子的时候
在这里插入图片描述
当弄清楚了数据的流向以后就需要明确板子的行列关系.

在这里插入图片描述
在这里插入图片描述

二、代码

ws2812screen.c文件

本代码段分别有initializeLedMapping(int boardRows, int boardCols, int rows, int cols)
其中的几个参数需要根据上面的自己填写。
void setLedColor(int x, int y, uint32_t colorValue) 是给点设置颜色的。设置完以后还要调用上篇文章的中
void WS2812_Send (void)进行发送。
你还可以调用void drawDigit(int digit, int startX, int startY, uint32_t colorValueOn, uint32_t colorValueOff) 这个函数来显示阿拉伯数字
void drawColon(int x, int y, uint8_t on,uint32_t colorValueOn) 函数是显示冒号的,为后续做时钟做准备。

显示3x5的阿拉伯数字的二维布尔数组的定义
显示一个阿拉伯数字最少需要3*5的灯珠

效果
在这里插入图片描述

#include "ws2812screen.h"#include "stdio.h"
#include "stdlib.h"int** ledMapping;int totalBoards;
int ledsPerBoard;  // LEDs per board
int rowsPerBoard;  // Rows per board
int colsPerBoard;  // Columns per board///*
//int boardCount	几行小板子
//int boardCols		几列小板子
//int rows		小板子中灯的行数
//int cols		小板子中灯的列数
//*/
void initializeLedMapping(int boardRows, int boardCols, int rows, int cols)
{totalBoards = boardRows*boardCols;rowsPerBoard = rows;colsPerBoard = cols;ledsPerBoard = rows * cols;  // Calculate total LEDs per board// Allocate memory for the mapping table  为映射表分配内存ledMapping = malloc(sizeof(int*) * totalBoards * colsPerBoard);  for(int i = 0; i < totalBoards; ++i){for(int j = 0; j < colsPerBoard; ++j){ledMapping[i*colsPerBoard+j] = malloc(sizeof(int) * rowsPerBoard * boardRows);  for(int m = 0; m < rowsPerBoard * boardRows; ++m){int panelIdx = i / boardCols;int panelLoc = i % boardCols;int localRow = m / rows;int localCol = m % rows;//检查它是偶数列还是奇数列if((panelLoc*colsPerBoard + j) % 2 == 0) {// 奇数 go from bottom to topledMapping[i*colsPerBoard+j][m] = (panelIdx * rowsPerBoard + localRow) * totalBoards * ledsPerBoard + panelLoc * ledsPerBoard + j * rows + localCol;}else {// 偶数 go from top to bottomledMapping[i*colsPerBoard+j][m] = (panelIdx * rowsPerBoard + localRow) * totalBoards * ledsPerBoard + panelLoc * ledsPerBoard + j * rows + rows - 1 - localCol;}}}}
}//void initializeLedMapping(int boardCount, int rows, int cols)
//{
//    totalBoards = boardCount;
//    rowsPerBoard = rows;
//    colsPerBoard = cols;
//    ledsPerBoard = rows * cols;  // Calculate total LEDs per board
//	
//    int panelIdx = i / 5;  // 获取面板的索引
//    int localX = i % 5;  // 获取在面板内的x坐标//    // Allocate memory for the mapping table
//    ledMapping = malloc(sizeof(int*) * totalBoards * colsPerBoard);  // 5 columns per board//    for(int i = 0; i < totalBoards * colsPerBoard; ++i)
//    {
//        ledMapping[i] = malloc(sizeof(int) * rowsPerBoard);  // 5 leds per column//        for(int j = 0; j < rowsPerBoard; ++j)
//        {
//            if((i % colsPerBoard) % 2 == 0)// 用于判断在当前面板内,LED的列号是奇数还是偶数
//            {
//                // 奇数列从下到上
//                ledMapping[i][j] = (i / colsPerBoard * ledsPerBoard) + (i % colsPerBoard * rowsPerBoard) + j;
//            }
//            else
//            {
//                // 偶数列从上到下
//                ledMapping[i][j] = (i / colsPerBoard * ledsPerBoard) + (i % colsPerBoard * rowsPerBoard) + (rowsPerBoard-1 - j);
//            }
//        }
//    }
//}//int** ledMapping;
//int totalBoards;
//int ledsPerBoard = 25;  // 5*5//void initializeLedMapping(int boardCount)
//{
    int panelIdx = i / 5;  // 获取面板的索引
    int localX = i % 5;  // 获取在面板内的x坐标
//    totalBoards = boardCount;//    // Allocate memory for the mapping table
//    ledMapping = malloc(sizeof(int*) * totalBoards * 5);  // 5 columns per board//    for(int i = 0; i < totalBoards * 5; ++i)
//    {
//        ledMapping[i] = malloc(sizeof(int) * 5);  // 5 leds per column//        for(int j = 0; j < 5; ++j)
//        {
//            if((i % 5) % 2 == 0)// 用于判断在当前面板内,LED的列号是奇数还是偶数
//            {
//                // 奇数列从下到上
//                ledMapping[i][j] = (i / 5 * ledsPerBoard) + (i % 5 * 5) + j;
//            }
//            else
//            {
//                // 偶数列从上到下
//                ledMapping[i][j] = (i / 5 * ledsPerBoard) + (i % 5 * 5) + (4 - j);
//            }
//        }
//    }
//}void setLedColor(int x, int y, uint32_t colorValue) 
{Set_LED_HEX(ledMapping[x][y], colorValue);
}void cleanupLedMapping(void)
{for(int i = 0; i < totalBoards * 5; ++i){free(ledMapping[i]);}free(ledMapping);
}
/*
你可以用 initializeLedMapping() 来初始化你的映射表,
用 setLedColor() 来设置LED颜色,最后用 cleanupLedMapping() 来释放内存。
注意,这个版本的代码使用了动态内存分配,
所以你需要确保在不再需要映射表的时候调用 cleanupLedMapping() 来避免内存泄漏。
*/uint8_t digits[10][5][3] = {{{1, 1, 1}, {1, 0, 1}, {1, 0, 1}, {1, 0, 1}, {1, 1, 1}}, // 0{{0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 1, 0}}, // 1{{1, 1, 1}, {0, 0, 1}, {1, 1, 1}, {1, 0, 0}, {1, 1, 1}}, // 2{{1, 1, 1}, {0, 0, 1}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, // 3{{1, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 0, 1}, {0, 0, 1}}, // 4{{1, 1, 1}, {1, 0, 0}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, // 5{{1, 1, 1}, {1, 0, 0}, {1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, // 6{{1, 1, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}}, // 7{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, // 8{{1, 1, 1}, {1, 0, 1}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, // 9
};
// 显示3x5的阿拉伯数字的二维布尔数组的定义void drawDigit(int digit, int startX, int startY, uint32_t colorValueOn, uint32_t colorValueOff) 
{for(int y = 0; y < 5; y++) {for(int x = 0; x < 3; x++) {if(digits[digit][y][x]) {setLedColor(startX + x, startY + y, colorValueOn);} else {setLedColor(startX + x, startY + y, colorValueOff);}}}
}
void drawColon(int x, int y, uint8_t on,uint32_t colorValueOn) 
{// 冒号由两个点表示setLedColor(x, y, on ? colorValueOn : 0x000000);   // top dotsetLedColor(x, y + 2, on ? colorValueOn : 0x000000);   // bottom dot
}

ws2812screen.h文件

#ifndef __WS2812_SCREEN_H#define __WS2812_SCREEN_H
#include "main.h"#include "ws2812b.h"//void initializeLedMapping(int boardCount);
//void initializeLedMapping(int boardCount, int rows, int cols);
void initializeLedMapping(int boardRows, int boardCols, int rows, int cols);void setLedColor(int x, int y, uint32_t colorValue);
void cleanupLedMapping(void);void drawDigit(int digit, int startX, int startY, uint32_t colorValueOn, uint32_t colorValueOff);
void drawColon(int x, int y, uint8_t on,uint32_t colorValueOn) ;#endif

主函数

initializeLedMapping(1,4,5,5);drawDigit(1,0,0,0x0F000F,0x000000);drawDigit(3,4,0,0x0F000F,0x000000);drawColon(7, 1, 1,0x0F000F);drawDigit(1,8,0,0x0F000F,0x000000);drawDigit(4,12,0,0x0F000F,0x000000);		WS2812_Send();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */drawColon(7, 1, 1,0x0F000F);WS2812_Send();HAL_Delay(1000);drawColon(7, 1, 0,0x0F000F);WS2812_Send();HAL_Delay(1000);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/28355.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达ML2022-用于手写数字识别的神经网络

1 用到的包 导入在这个分配过程中需要的所有包。 Numpy 是使用 Python 进行科学计算的基本软件包。Matplotlib 是在 Python 中绘制图形的流行库。tensorflow是一种流行的机器学习平台。 import numpy as np import tensorflow as tf from tensorflow.keras.models import Se…

【运维】第04课:入口网关服务注册发现-Openrety 动态 uptream

本课时,我将带你一起了解入口网关服务的注册发现,并使用 OpenResty 实现一套动态 Upstream。 课前学习提示 基于本课时我们将要学习的内容,我建议你课前先了解一下 Nginx 的基础,同时熟悉基础的 Lua 语言语法,另外再回顾一下 HTTP 的请求过程,对于 Nginx 的负载均衡基本…

idea新建xml模板设置,例如:mybatis-config

在idea怎么新建mapper.xml文件&#xff0c;具体操作步骤和结果如下&#xff0c;其他文件也是可以自定义模板的流程和步骤一致&#xff01; 效果如下&#xff1a; 步骤如图&#xff1a; step1&#xff1a; step2&#xff1a; 文件内容&#xff1a; <?xml version"…

vue复习

1.mustache动态插值 <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initial-scale…

常见的前端安全以及常规安全策略

1、CSRF&#xff1a;跨站请求伪造&#xff08;Cross-site request forgery&#xff09;&#xff1b; 原理&#xff1a; &#xff08;1&#xff09; 用户C打开浏览器&#xff0c;访问受信任网站A&#xff0c;输入用户名和密码请求登录网站A&#xff1b; &#xff08;2&#xff…

python VTK vtkImplicitBoolean 布尔切割

VTK中包含可以执行布尔操作的接口有vtkImplicitBoolean&#xff0c;vtkBooleanOperationPolyDataFilter&#xff0c;vtkLoopBooleanPolyDataFilter。 布尔操作包括&#xff1a;布尔加&#xff0c;布尔减和布尔交。 code: #!/usr/bin/env python""" This examp…

阿里云 OSS 静态网站托管

本文节选自我的博客&#xff1a;阿里云 OSS 静态网站托管 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是MilesChen&#xff0c;偏前端的全栈开发者。&#x1f4dd; CSDN主页&#xff1a;爱吃糖的猫&#x1f525;&#x1f4e3; 我的博客&#xff1a;爱吃糖的猫&…

基于虚拟同步发电机控制的双机并联MATLAB仿真模型

使用MATLAB2021b打开 主要内容&#xff1a; 功率计算模块、虚拟同步发电机控制模块、电压合成模块、电压电流双环控制模块&#xff01; 1.两台VSG并联&#xff0c;开始各自带负载10KW&#xff0c;在0.3秒的时候加入公共负载10KW&#xff0c;稳定后两台VSG可以均分公共负载的…

数据结构--时间复杂度与空间复杂度

数据结构–时间复杂度与空间复杂度 文章目录 数据结构--时间复杂度与空间复杂度时间复杂度一、什么是时间复杂度二、具体实例1.大O的渐进表示法2.二分查找的时间复杂度 空间复杂度一、什么是空间复杂度二、具体实例总结 时间复杂度 一、什么是时间复杂度 在计算机科学中&…

华为数通智选交换机S5735S-L24T4S-QA2无法SSH远程访问

以前都是按照华为S5700交换机开启SSH远程访问方法配置不同网段通过静态路由实现互通,华为S5700交换机开启ssh远程登陆,现在新买的华为数通智选交换机S5735S-L24T4S-QA2,也是按照这步骤配置,令人不解的是,竟然无法ssh访问,仔细看了配置也没有发现问题,在华为eNSP模拟器上验…

C++进阶—哈希/unordered系列关联式容器/底层结构(一篇文章学习哈希)

目录 0. 前言map/set和unordered_map/unordered_set 1. unordered系列关联式容器 1.1 unordered_map 1.1.2 unordered_map的接口说明 1. unordered_map的构造 2. unordered_map的容量 3. unordered_map的迭代器 4. unordered_map的元素访问 5. unordered_map的查询 6…

基于STM32的智能喂养系统

基于STM32的智能喂养系统 系统简介 自动检测环境温湿度&#xff0c;当温湿度低于阈值时自动打开加湿器&#xff1b;自动检测水位&#xff0c;当水位低于阈值时自动加水&#xff1b;自动检测有害气体&#xff0c;当检测到有害气体时自动打开风扇&#xff1b;同步状态到微信小程…