新闻详情

GD32L233C-START电位器+ws2812做一个简易可调灯色的灯环

 二维码
发表时间:2022-03-30 10:11
文章附图

2022年也过去了3个月。年后因为种种原因,所以评测的事也停了一段时间,今天趁着有空,就又拿起板子捣鼓起来了。

今天的话分享的也不多,就利用电位器加一个WS2812灯环,做一个可调灯色的灯环。使用到的芯片外设主要有两块,一个是模数转换器(ADC),另一个则是串行外设接口(SPI)。

模块说明

旋转电位器用到的是下图的这种,某宝上购买的,内部实际上是一个可调电阻,模拟输出电压0~5V。计划通过读取该模块电压的模拟量来调节WS2812灯环的灯色。

  WS2812灯环,同样也是在某宝上淘来的,由8个WS2812灯珠串联起来的灯环(如下图)。关于WS2812的介绍,简单的说,这是一种可通过编程来实现调节灯色的灯珠,因为它内部集成了控制电路和发光电路。


按照它的时序要求,我们可以通过发送的数据来控制WS2812C的灯色。以下是它的引脚定义,数据结构,时序图等基本资料


在这里插入图片描述

数据传输方法:

在这里插入图片描述

数据结构:

在这里插入图片描述

数据传输时间:

在这里插入图片描述

时序波形图

在这里插入图片描述

了解完WS2812的基本信息后,接下来就是如何编程控制了。我们可以从上面的时序波形图和波形时序说明图上看到,WS2812C的时序控制要求达到ns级别,如果说使用IO翻转来实现对它的控制,一方面是难以实现(IO翻转的时间不一定有这么快),另一方面是程序的可移植性也会很差,因此,我们这里采用另一种方法,利用芯片自带的SPI+DMA来实现对WS2812的驱动。

SPI驱动原理说明

关于SPI驱动WS2812原理的说明,这里也不详细介绍,网上大把资料,讲得也比较细。简单说,就是通过SPI外设输出一帧数据,通过这帧数据的高低电平(0和1)占比,来模拟上图码型中的0码和1码。举个例子,我通过调节SPI的分频器,来使得SPI输出一帧数据(通常是8位)的时间周期是1us,那么,这个时候,假如我输出的数据是0xF0,那么这一帧数据所对应的码型就是上图中的0码,若是我输出的数据是0xC0,那么这一帧数据所对应的码型就是上图中的1码。另外,之所以选择SPI+DMA的控制方案,则是考虑到如果在频繁调光的情况下,利用DMA可以极大减轻CPU的负担。

编程实现

首先是关于电位器模拟量的读取功能,用到了MCU的ADC外设,引脚的使用如下:

  • #define ROTATION_SENSOR_GPIO_RCU        (RCU_GPIOB)


  • #define ROTATION_SENSOR_GPIO_PORT       (GPIOB)

  • #define ROTATION_SENSOR_GPIO_PIN        (GPIO_PIN_0)


  • #define ROTATION_ADC_CH                 (ADC_CHANNEL_8)

adc初始化

  • /*!

  •     \brief      configure the different system clocks

  •     \param[in]   none

  •     \param[out] none

  •     \retval     none

  • */

  • staticvoid rcu_config(void)

  • {

  • /* enable ADC clock */

  •     rcu_periph_clock_enable(RCU_ADC);

  • /* config ADC clock */

  •     rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);

  • }


  • /*!

  •     \brief      configure the ADC peripheral

  •     \param[in]   none

  •     \param[out] none

  •     \retval     none

  • */

  • staticvoid adc_config(void)

  • {

  • /* ADC data alignment config */

  •     adc_data_alignment_config(ADC_DATAALIGN_RIGHT);

  • /* ADC channel length config */

  •     adc_channel_length_config(ADC_REGULAR_CHANNEL, 1U);


  • /* ADC trigger config */

  •     adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);

  • /* ADC external trigger config */

  •     adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);


  • /* enable ADC interface */

  •     adc_enable();

  •     delay_1ms(1U);

  • /* ADC calibration and reset calibration */

  •     adc_calibration_enable();

  • }


  • staticvoid gpio_config(void)

  • {

  •     rcu_periph_clock_enable(ROTATION_SENSOR_GPIO_RCU);  

  • /* PB0 ADC_IN config */

  •     gpio_mode_set(ROTATION_SENSOR_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ROTATION_SENSOR_GPIO_PIN);

  • }


  • static uint16_t ADC_Get_Channel(uint8_t channel)

  • {

  • /* ADC regular channel config */

  •     adc_regular_channel_config(0U, channel, ADC_SAMPLETIME_7POINT5);

  • /* ADC software trigger enable */

  •     adc_software_trigger_enable(ADC_REGULAR_CHANNEL);


  • /* wait the end of conversion flag */

  • while(!adc_flag_get(ADC_FLAG_EOC));

  • /* clear the end of conversion flag */

  •     adc_flag_clear(ADC_FLAG_EOC);

  • /* return regular channel sample value */

  • return (adc_regular_data_read());   

  • }


  • void rotationSensorInit(void)

  • {

  •     gpio_config();

  •     rcu_config();

  •     adc_config();

  • }

读取ADC模拟量

  • adcval = ADC_Get_Channel(ROTATION_ADC_CH);


接下来是SPI+DMA驱动WS2812部分

先是引脚的定义

  • #define SPI1_MOSI_RCU            (RCU_GPIOC)


  • #define WS2812_RCU_PERIPH(RCU_SPI1)

  • #define WS2812_PERIPH(SPI1)


  • #define WS2812_MOSI_PORT          (GPIOC)

  • #define WS2812_MOSI_PIN           (GPIO_PIN_12)


  • #define WS2812_LOW(0xC0)

  • #define WS2812_HIGH(0xF0)


  • static uint8_t u8TxBuffer[24] = {0};

  • static uint16_t u16BufferCnt = 0;

SPI+DMA初始化

  • /**

  • *******************************************************************************

  • ** \brief Configure SPI DMA function

  • **

  • ** \param [in] None

  • **

  • ** \retval None

  • **

  • ******************************************************************************/

  • staticvoid Spi_DmaConfig(void)

  • {

  •     dma_parameter_struct dma_init_struct;

  • /* enable DMA clock */

  •     rcu_periph_clock_enable(RCU_DMA);


  • /* initialize DMA channel 0 */

  •     dma_deinit(DMA_CH0);

  •     dma_struct_para_init(&dma_init_struct);

  •     dma_init_struct.request      = DMA_REQUEST_SPI1_TX;

  •     dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;

  •     dma_init_struct.memory_addr   = (uint32_t)u8TxBuffer;

  •     dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;

  •     dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;

  •     dma_init_struct.number       = 24;

  •     dma_init_struct.periph_addr   = (uint32_t)&SPI_DATA(WS2812_PERIPH);

  •     dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;

  •     dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;

  •     dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;

  •     dma_init(DMA_CH0, &dma_init_struct);

  • }


  • void WS2812C_Init(void)

  • {

  •     spi_parameter_struct spi_init_struct;


  •     rcu_periph_clock_enable(SPI1_MOSI_RCU);

  •     rcu_periph_clock_enable(WS2812_RCU_PERIPH);


  • /* SPI1_MOSI(PC12) GPIO pin configuration */

  •     gpio_af_set(WS2812_MOSI_PORT, GPIO_AF_5, WS2812_MOSI_PIN);

  •     gpio_mode_set(WS2812_MOSI_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, WS2812_MOSI_PIN);

  •     gpio_output_options_set(WS2812_MOSI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, WS2812_MOSI_PIN);


  •     spi_i2s_deinit(WS2812_PERIPH);


  • /* SPI1 parameter config */

  •     spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;

  •     spi_init_struct.device_mode          = SPI_MASTER;

  •     spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;

  •     spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;

  •     spi_init_struct.nss                  = SPI_NSS_SOFT;//CS脚由软件托管

  •     spi_init_struct.prescale             = SPI_PSC_4;

  •     spi_init_struct.endian               = SPI_ENDIAN_MSB;

  •     spi_init(WS2812_PERIPH, &spi_init_struct);


  • /* configure SPI1 byte access to FIFO */

  •     spi_fifo_access_size_config(WS2812_PERIPH, SPI_BYTE_ACCESS);


  •     spi_dma_enable(WS2812_PERIPH, SPI_DMA_TRANSMIT);


  • /* enable SPI1 */

  •     spi_enable(WS2812_PERIPH);


  •     Spi_DmaConfig();

  • }

数据发送

  • staticvoid RGB_Set_Up(void)

  • {

  • u8TxBuffer[u16BufferCnt] = WS2812_HIGH;

  •     u16BufferCnt++;

  • }


  • staticvoid RGB_Set_Down(void)

  • {

  • u8TxBuffer[u16BufferCnt] = WS2812_LOW;

  •     u16BufferCnt++;

  • }


  • void WS2812C_SetRGB(uint32_t RGB888)

  • {

  • int8_t i = 0;

  • uint8_t byte = 0;

  •     u16BufferCnt = 0;


  • for(i = 23; i >= 0; i--)

  • {

  • byte = ((RGB888>>i)&0x01);

  • if(byte == 1)

  • {

  • RGB_Set_Up();

  • }

  • else

  • {

  • RGB_Set_Down();

  • }

  • }



  •     dma_transfer_number_config(DMA_CH0, 24);

  •     dma_channel_enable(DMA_CH0);


  • while (RESET == dma_flag_get(DMA_CH0, DMA_FLAG_FTF))

  • {

  • }

  • dma_flag_clear(DMA_CH0, DMA_FLAG_FTF);

  •     dma_channel_disable(DMA_CH0);

  • }

灯环控制接口

  • void ws2812c_All_Ctrl(uint32_t RGB888)

  • {

  • uint8_t i = 0;

  • for(i = 0; i < WS2812C_LED_NUM; i++)

  • {

  • WS2812C_SetRGB(RGB888);

  • }

  • }

关于模块的驱动部分大致就这样,然后我们在利用板载的WAKEUP KEY按键来转换电位器所控制的RGB灯色,剩下的就是一些应用逻辑功能的实现。

最新文章
>
2022-09-17
>
2022-09-17
>
2022-09-17
>
2022-09-17
>
2022-09-17
>
2022-08-28
>
2022-08-28
>
2022-08-27
>
2022-08-27
>
2022-08-27
随机文章
>
  LED电子显示屏很重要的组成部分就有LED单元板,如果单元板有问题,会直影响LED显示屏的整体质量!所以,如何辨别LED单元板的好坏是LED显示屏商家关心的问题,下面整理了一些检测LED单元板的常见方法。  一、材质  1. LED单元板板材  有些LED单元板厂家为了低价竞争,采用廉价的阻燃纸质板或者是单面纤维板作为LED灯的PCB线路板。因为全玻纤PCB板很贵。刚开始看不出差别,一般...
>
  8月17日,福建泉州市2022年重大项目视频连线开工活动在晋江举行。据悉,晋江市此次共22个项目集中开工,总投资965.5亿元,涵盖光电显示等多个领域。  此次集中开工活动中,位于高端制造产业园的MiniLED封装产业项目作为安溪县的代表性重大项目,向全市展示开工场面。    图片来源:安溪县融媒体中心  据悉,安溪县MiniLED封装产业项目总投资11.67亿元,年度计划投资1.5亿元...
>
  1:幻彩灯珠简介  1.1 幻彩内置IC灯珠的特点  幻彩内置IC灯泡主要有两个部分:一个是LED,另一个是IC晶体管。LED部分负责产生光,而IC晶体管则负责控制LED的亮度和颜色。通常情况下,一个幻彩内置IC灯泡包含三个不同颜色的LED:红、 绿、 和 蓝 (RGB) 。 控制晶体 管开关的电流大小,来调整 LED的亮度。而通过不同比例地控制三个 LED的亮度,可以得到不同颜色的光。...
>
  led灯在我们的生活中使用极广,同时在使用led灯时还会出现一些故障,如只发弱光,甚至是不亮了。面对这些情况应该怎么办?  一、led灯只发弱光怎么回事  电源参数主要注意两个,一个是瓦数,一个是电源输出电压(也就是灯板上的输入DC电压)。  也可能是灯的驱动电源损坏了,若是独立电源,可买个相同规格的更换,若是一体的,建议整灯更换。  还有可能是led灯泡的问题,也可以再买个灯泡看看。 ...
>
  led灯是现代生活中再常见不过的灯具,人们选择led灯时会考虑其使用寿命,更需要注意保养。究竟led灯怎么保养?  一、led灯的使用寿命多少  正常来说,led灯的使用寿命差不多都是能够达到4万小时到5万小时的,这个跟led灯的品牌和性能是有很大的关系的,像大品牌的led灯各方面还是比较有保障的,使用寿命久,而且质量也是非常不错的,不容易出现问题。  现在led灯的应用还是非常广泛的,...
>
  led灯不亮怎么回事  led灯是我们生活中再常见不过的灯具,led灯在使用过程中容易出现不亮的情况,究竟是怎么回事?不亮的话怎么修理呢  一、led灯不亮怎么回事  1、led灯条的焊接点有虚焊现象,运输过程中的震动造成焊点脱落而导致灯带不亮。  2、焊锡质量不好,led灯条在弯折的过程中焊点容易产生脆裂、脱落现象。  3、安装时弯折角度过大,造成led灯条焊点与铜箔分离而导致不亮。 ...
>
  对于led灯人们都并不陌生,甚至我们生活中大部分灯具都是led灯,led灯在使用过程中可能会出现一些问题,如不亮或者变弱的问题   一、led灯不亮怎么办  1、关掉开关,在折叠梯子的帮助下,拆掉led吸顶灯的外壳,并检查灯管是否出现发黑发暗的地方。如果有,很有可能是灯管已经损坏了。必须更换了,这种LED灯管在五金商店里面可以买到,建议选择知名品牌。  2、如果灯管还是完好的,那么应该试...

关于天成    产品中心    新闻资讯    技术支持    人力资源    联系方式

联系我们

----------------------------------------------

电话:4008-320-328 /   0755-29573979   

传真:0755-29573533

邮件:tczm@tczmled.com   邮编:518000

地址:深圳市宝安区松岗街道东方大道33号第四栋

邮箱:jiangeng@tczmled.com   (投诉与合作)


(关注我们)
_____________________________________________________________________________________________________________________________________________________________________________________________________________________________
_____________________________________________________________________________________________________________________________________________________________________________________________________________________________

友情链接: led光源LED灯带 | 洗地机‍ |   | 方木多片锯‍ | 泰兴减速机‍ | led灯珠‍ ‍‍ | 网带输送机‍‍    | 波峰焊‍ |   滚针轴承|   高温退火炉   |   试验筛 |   螺旋叶片 |   梅花联轴器 ‍ |   电热管‍   |   青岛电缆桥架‍‍ | N80石油套管‍   | 玻璃钢冷却塔‍ | 西安装修公司

会员登录
登录
其他帐号登录:
我的资料
留言
回到顶部