新闻详情

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灯色,剩下的就是一些应用逻辑功能的实现。

随机文章
  3570是1860全新升级吗?  3570和1860实际上全是指灯珠的尺寸,3570表明灯珠尺寸是3.5*7.0mm,1860指的是灯珠尺寸为1.8*6.0mm。  假如一样的色度下,一颗3570灯珠可以替代2颗1860。因此,不能说是更新,只有说加工工艺不一样而已。应用哪一种,应当和灯珠的价钱,加工工艺的简单化关联大一点。3570加工工艺通俗一点,色度还更高。可是处理速度高,表明发烫更...
3535灯珠在汽车灯具中的应用是当前的主流趋势。5050灯珠是5mm*5mm*1.6mm,光强高(纯白光,暖光的稍微小一点)。他的工作电压和普通的LED一样,只需要3.0-3.4V,电流也是一样60MA。UVC灯珠工艺难点在于点胶量的控制,在胶体高度、点胶位置均有详细的工艺要求。幻彩灯珠应用于:LED幻彩灯带,LED幻彩灯条,LED柔性霓虹管,LED硬灯条,LED S形灯带,玩具,仪器,数码...
2835LED灯珠分为白光和色光,色光有多种颜色,在不同的地方和环境中安装不同颜色的2835灯珠,不同颜色的2835LED灯珠可以营造不同的氛围,感染情绪。白光灯珠相对于小功率LED灯珠来说,led大功率灯珠的功率更高,亮度更亮,价格更高。...
LED次品灯为用户敲响了一个警钟市场上的LED照明产品种类繁多的LED,而线性增加,LED灯制造商越来越激增。幻彩灯珠应用于:LED幻彩灯带,LED幻彩灯条,LED柔性霓虹管,LED硬灯条,LED S形灯带,玩具,仪器,数码产品等区域使用。...
2018年8月30日,广东汕头地区连续暴雨,造成严重水灾。天成照明总经理林坚耿先生通过深圳市潮汕商会踊跃捐资,为受灾群众的及时援助和灾后重建奉献了一份爱心和力量。深圳市潮汕商会特此颁发《感谢状》以表彰其仁心仁爱。
2018年11月26日,深圳狮子会陆丰助学“幸福奖教奖学金项目”活动在广东省陆丰市甲东镇15所小学展开,天成照明作为狮子会成员对此次活动给予了大力支持,受到甲东镇人民政府、陆丰市教育局、深圳狮子会的肯定。
2019年1月10日,深圳市照明与显示工程行业协会(SLDA)年会在深圳登喜路国际大酒店隆重举行。天成照明深受深圳市照明与显示工程行业协会及社会公众的肯定和支持,荣膺“2018年度特别贡献奖”、“光爱100贫困大学生帮扶计划工公益大使”荣誉...
2019年09月12日下午,深圳市天成照明有限公司围绕“月满金秋 · 情系天成”的主题在宝安区华美酒店召开2019金秋丰收季表彰大会暨中秋家宴。天成照明总经办林坚耿先生、李浩锐先生等全体天成人出席了本次年度大会。在本次大会中,人力资源部、财...

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

联系我们

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

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

传真:0755-29573533

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

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

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


(关注我们)
_____________________________________________________________________________________________________________________________________________________________________________________________________________________________
_____________________________________________________________________________________________________________________________________________________________________________________________________________________________

友情链接: led光源LED灯带 | 洗地机‍ | 不锈钢无缝管‍   | 方木多片锯‍ | 泰兴减速机‍ | led灯珠‍ | 湿电除尘‍ | 铝挤压型材‍‍ | 网带输送机‍‍ |   电动叉车‍    |   手术无影灯‍    | 波峰焊‍ |   滚针轴承|   高温退火炉   |   试验筛 |   螺旋叶片 |   梅花联轴器 ‍ |   电热管‍   |   青岛电缆桥架‍‍ | N80石油套管‍ |   不锈钢焊管‍ | 玻璃钢冷却塔‍ | 干式变压器‍ | 墙布‍ | 西安装修公司‍ | ‍ 工矿灯

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