为了薅一下学校的羊毛,在大一的时候就参加了一下科技节,当时是刚刚开始学习32单片机,还不是很熟练,并且还是用库函数做的,这一篇就先讲一下用32单片机的库函数,简单的对ws2812b做编程。

我用的是正点原子精英版,stm32f103c8t6,之所以用这块呢纯属与于自己大一时不会模电,而且正点原子的教程是真的不错,含泪用将近300大洋买了一块,但最后在做测试的时候,学长就跟我说买亏了,(欲哭无泪.pdf)——

总体来说是不难的

【【正点原子】STM32F103开发板教程入门篇】 https://www.bilibili.com/video/BV1Vo4y1m7ct/?share_source=copy_web&vd_source=900c0b43c89920f59c7bc857e7204a03

跟着这个教程听第10讲将环境搭建好,这个地方要格外的小心,我试了好几遍才成功的。

一、添加ws2812.c和ws2812.h文件

直接使用正点原子模板向HARDWARE文件夹下,新建一个文件夹命名为ws2812,然后新建ws2812.c和ws2812.h。

然后把一下文件分别复制到对应c和h文件

1、ws2812.h

#ifndef __WS2812_H
#define __WS2812_H#include "stm32f10x.h"#define PIXEL_NUM 60//硬件spi模拟ws2811时序(用spi的8位数据模拟ws281x的一位数据)
//要将系统时钟设置为56M,分频数设置为8,则SPI的通信频率为7M,传输一位数据的时间约为143纳秒(ns)
//3*143 = 429ns   5*143 = 715ns  符合WS281X芯片的通信时序。
//  _____
// |     |___|   11111000  high level
//  ___
// |   |_____|   11100000  low level#define WS_HIGH 0XF8
#define WS_LOW  0XE0void ws281x_init(void);
void ws281x_closeAll(void);
void ws281x_rainbowCycle(uint8_t wait);
uint32_t ws281x_color(uint8_t red, uint8_t green, uint8_t blue);
void ws281x_setPixelColor(uint16_t n ,uint32_t GRBcolor);
void ws281x_show(void);void ws281x_theaterChase(uint32_t c, uint8_t wait);
void ws281x_colorWipe(uint32_t c, uint8_t wait);
void ws281x_rainbow(uint8_t wait);
void ws281x_theaterChaseRainbow(uint8_t wait);#endif /* __WS2812_H */

2、ws2812.c

#include "ws2812.h"
#include "usart.h"
#include "delay.h"uint8_t pixelBuffer[PIXEL_NUM][24] ;void ws281x_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef  SPI_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //PORTA时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //SPI1时钟使能     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输/* PA7  SPI1_MOSI */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PA7复用推挽输出 SPIGPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOASPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;        //串行同步时钟的空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;  //串行同步时钟的第2个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;     //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;       //定义波特率预分频的值:波特率预分频值为16SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;  //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI1, ENABLE); //使能SPI外设SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);DMA_DeInit(DMA1_Channel3);   //将DMA的通道1寄存器重设为缺省值DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1 -> DR); //cpar;  //DMA外设ADC基地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pixelBuffer; //cmar;  //DMA内存基地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //数据传输方向,从内存读取发送到外设DMA_InitStructure.DMA_BufferSize = PIXEL_NUM * 24; //cndtr;  //DMA通道的DMA缓存的大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //外设地址寄存器不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度为8位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  //工作在正常缓存模式DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输DMA_Init(DMA1_Channel3, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器 ws281x_closeAll();  //关闭全部的灯delay_ms(100); //关闭全部的灯需要一定的时间
}void ws281x_closeAll(void)
{uint16_t i;uint8_t j;for(i = 0; i < PIXEL_NUM; ++i){for(j = 0; j < 24; ++j){pixelBuffer[i][j] = WS_LOW;}}ws281x_show();
}uint32_t ws281x_color(uint8_t red, uint8_t green, uint8_t blue)
{return green << 16 | red << 8 | blue;
}void ws281x_setPixelColor(uint16_t n ,uint32_t GRBcolor)
{uint8_t i;if(n < PIXEL_NUM){for(i = 0; i < 24; ++i){pixelBuffer[n][i] = (((GRBcolor << i) & 0X800000) ? WS_HIGH : WS_LOW);}}
}void ws281x_setPixelRGB(uint16_t n ,uint8_t red, uint8_t green, uint8_t blue)
{uint8_t i;if(n < PIXEL_NUM){for(i = 0; i < 24; ++i){pixelBuffer[n][i] = (((ws281x_color(red,green,blue) << i) & 0X800000) ? WS_HIGH : WS_LOW);}}
}void ws281x_show(void)
{DMA_Cmd(DMA1_Channel3, DISABLE );  //关闭USART1 TX DMA1 所指示的通道 DMA_ClearFlag(DMA1_FLAG_TC3);    DMA_SetCurrDataCounter(DMA1_Channel3,24 * PIXEL_NUM );//DMA通道的DMA缓存的大小DMA_Cmd(DMA1_Channel3, ENABLE);  //使能USART1 TX DMA1 所指示的通道
}// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t ws281x_wheel(uint8_t wheelPos) {wheelPos = 255 - wheelPos;if(wheelPos < 85) {return ws281x_color(255 - wheelPos * 3, 0, wheelPos * 3);}if(wheelPos < 170) {wheelPos -= 85;return ws281x_color(0, wheelPos * 3, 255 - wheelPos * 3);}wheelPos -= 170;return ws281x_color(wheelPos * 3, 255 - wheelPos * 3, 0);
}// Fill the dots one after the other with a color
void ws281x_colorWipe(uint32_t c, uint8_t wait) {for(uint16_t i=0; i<PIXEL_NUM; i++) {ws281x_setPixelColor(i, c);ws281x_show();delay_ms(wait);}
}void ws281x_rainbow(uint8_t wait) {uint16_t i, j;for(j=0; j<256; j++) {for(i=0; i<PIXEL_NUM; i++) {ws281x_setPixelColor(i, ws281x_wheel((i+j) & 255));}ws281x_show();delay_ms(wait);}
}// Slightly different, this makes the rainbow equally distributed throughout
void ws281x_rainbowCycle(uint8_t wait) {uint16_t i, j;for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheelfor(i=0; i< PIXEL_NUM; i++) {ws281x_setPixelColor(i,ws281x_wheel(((i * 256 / PIXEL_NUM) + j) & 255));}ws281x_show();delay_ms(wait);}
}//Theatre-style crawling lights.
void ws281x_theaterChase(uint32_t c, uint8_t wait) {for (int j=0; j<10; j++) {  //do 10 cycles of chasingfor (int q=0; q < 3; q++) {for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, c);    //turn every third pixel on}ws281x_show();delay_ms(wait);for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, 0);        //turn every third pixel off}}}
}//Theatre-style crawling lights with rainbow effect
void ws281x_theaterChaseRainbow(uint8_t wait) {for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheelfor (int q=0; q < 3; q++) {for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, ws281x_wheel( (i+j) % 255));    //turn every third pixel on}ws281x_show();delay_ms(wait);for (uint16_t i=0; i < PIXEL_NUM; i=i+3) {ws281x_setPixelColor(i+q, 0);        //turn every third pixel off}}}
}

这两段是我直接帮你们敲好的,想要自己学习的话可以去看上面的教程,教程上只会教你怎么使用MAX7219点阵模块,但我认为这两种之间的编程是一样的。

最后将所有文件加到Keil 中,这个在教程10里也有,

如果你没出错的话文件夹里应该是这样的

在USER中应该是

在ws2812.c中我已经把函数全部敲好了,想要什么颜色就自己去找淘宝的卖家查一下ws2812的颜色配置,在mail中输入就可以了。

上传代码到单片机,VCC、GND正常接,信号线接到PA7,

结束。

多提一句如果你在烧录的时候发现抱错,最好检查一下自己的接线,还有要按REREST才会亮。

ws2812的教程到此结束,具体的制作看这【千里江山灯over~成品和所需材料都在视频之后,学起来~】 https://www.bilibili.com/video/BV19G4y1q7Tv/?share_source=copy_web&vd_source=900c0b43c89920f59c7bc857e7204a03

我们在最后还加了蓝牙和红外模块,这个另外再发一篇吧。

具体的代码看着:

链接:https://pan.baidu.com/s/144CuXr-Mv_HqLx7TO_8hRg 
提取码:7b6k

我们还做了报告书想要的也可以。。。

这个是我们最后的成果,有流水灯,和呼吸灯。

大一科技界做的LED装饰灯相关推荐

  1. 学计算机大一入实验室,上大一就可以做科研的上科大:充分尊重第一志愿,一半新生学计算机...

    原标题:上大一就可以做科研的上科大:充分尊重第一志愿,一半新生学计算机 今天(9月14日),在上海科技大学2018级新生的开学典礼上,学生们的名字被教授一个一个念出,大屏上随之展示着每一个学生的照片和 ...

  2. STC15F104E做的LED小台灯(USB供电+3级触摸调光+掉电记忆)

    STC15F104E做的LED小台灯(USB供电+3级触摸调光+掉电记忆) 主要特点: 3级亮度(就是亮1.2.3个LED,非PWM无闪烁) 触摸控制(本来是做电容式的,实际上需要触碰到电极) 掉电状 ...

  3. 手把手教你做智能LED灯(一) 功能规划与设计方案

    前言 智能硬件有意思,现在市场上有很多针对普通消费者的智能硬件.例如,智能灯泡.智能插座.智能电子秤,甚至无人飞行器.抛开这些智能设备实现的功能不谈,它们的实现原理都是大同小异:通过手机的蓝牙(或者w ...

  4. 手把手教你做智能LED灯(三) 手机控制端开发

    第3节 手机控制端开发 Arduino开发板已经可以接收命令了.接下来就要开始考虑手机端如何控制LED灯. 我们在之前一篇文档中开发过蓝牙聊天应用,那里面详细介绍了蓝牙设备互相连接的原理和实现方法.在 ...

  5. python程序 led灯闪烁_树莓派python编程 做一个LED呼吸灯

    玩转树莓派 2017-07-09 22:52 呼吸灯 概述 上一篇 我们通过控制GPIO口输出高低电平来控制一只 LED 的亮灭.这次我们来控制 LED 的亮度,灯由暗渐渐变亮,再由亮渐渐边暗,反复循 ...

  6. 大一适合做什么副业?适合在大学里做的副业

    大学兼职挺多的,如果你单纯为了赚点生活费,那随便找就行了,发传单.促销员.售货员等大把,还有做客服的等等;不过建议你得考虑一下自己适合做什么,关键是能学到点东西,要有目的的锻炼自己,为以后工作或事业打 ...

  7. 大一期间做的小游戏*4记录

    吾皇和巴扎黑的日常 刚学C只能在小黑框里玩文字游戏,于是就有了这个--激烈的菜鸡互啄!益智的无脑对决! 工程总共4个.c,1个.h,大概800行代码,大部分都在--讲故事 真是幼稚而美好的开始 鱼 发 ...

  8. 如何做 销售LED显示屏

    一个合格的销售人员.但能够清楚的描述所销售产品的FAB却很少LED销售点评,也不会重视那些与他们的实际需求无关的的利益. 销售人员没有提问和倾听,测试结果A公司大获全胜.也不了解客户的真正需求,要么是 ...

  9. WS2812串行可控彩色LED灯珠

    简 介: 利用ESP32中的硬件SPI控制WS2812的显示.使用了高频三极管9018 作为输出接口反向器,确定合适的电阻参数,验证了驱动方案的硬件和软件的可行性. 关键词: WS2812,ESP32 ...

最新文章

  1. Android L 仍需改善的三个问题
  2. jQuery 属性操作——案例:购物车案例模块
  3. linux服务器环境要求,在Linux服务器中配置node环境
  4. es过滤html标签,Elasticsearch 分词器
  5. Nginx核心模块——HTTP中的配置指令location和rewrite介绍
  6. c++面向对象三大特征封装、继承和多态知识总结
  7. 报错:out cannot be resolved【已解决】
  8. php 定义函数和访问,PHP-预定义函数访问数据库
  9. OpenLDAP的安装测试及管理
  10. 面试鹅厂,我三面被虐的体无完肤……
  11. react native进一步学习(NavigatorIOS 学习)
  12. python爬虫什么意思-Python为什么叫爬虫?Python与爬虫有什么关系?
  13. 保留五天的日志 php,怎样让日志在归档目录保留5天?
  14. LVM详解;Linux逻辑卷管理
  15. linux更改库文件vfp,VFP数据库修改与删除的基本操作
  16. python snownlp_snownlp · PyPI
  17. Linux 入门必备命令
  18. MSOCache是什么?
  19. js贷款还款计算:等额本金、等额本息、先息后本、等本等息
  20. php转foloat,PHP: Descrierea directivelor de bază ale php.ini - Manual

热门文章

  1. 【大学物理学】质点运动学
  2. OK6410开发板系统安装---嵌入式回归第二篇
  3. 1346 连分数(题目)
  4. 横跨欧亚大陆的城市-----★美丽的伊斯坦布尔★游记
  5. 【ESP 保姆级教程】疯狂毕设篇 —— 案例:基于ESP8266的WiFi自动打卡考勤系统
  6. 单片机菜鸟哥的大学四年以及工作七年,献给迷茫的电子物联网类的师弟师妹,绝对干货
  7. ECharts中visualMap的piecewise使用详解
  8. 别人的 阿里校招 面试总结
  9. 一个线程两次调用sart()方法会出现什么情况?
  10. 一篇入门级Scrapy框架(校花网)