2613|4

35

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【GD32L233C-START评测】4、电位器+ws2812做一个简易可调灯色的灯环 [复制链接]

本帖最后由 emmnn 于 2022-3-2 00:02 编辑

前言

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

今天的话分享的也不多,就利用电位器加一个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
  • */
  • static void 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
  • */
  • static void 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();
  • }
  • static void 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
  • **
  • ******************************************************************************/
  • static void 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();
  • }

数据发送

  • static void RGB_Set_Up(void)
  • {
  • u8TxBuffer[u16BufferCnt] = WS2812_HIGH;
  • u16BufferCnt++;
  • }
  • static void 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灯色,剩下的就是一些应用逻辑功能的实现。最后效果如下:


工程见附件!以上就是今天介绍的全部内容,如有错误,欢迎大家指出!

Template.7z

649.34 KB, 下载次数: 11

此帖出自GD32 MCU论坛

最新回复

感谢分享,这个帖子写的很详细。目前还没有看到错误的地方!   详情 回复 发表于 2022-3-2 10:07
点赞(1) 关注(2)
 

回复
举报

9864

帖子

24

TA的资源

版主

沙发
 

感谢分享,这个帖子写的很详细。

此帖出自GD32 MCU论坛
 
 
 

回复

2

帖子

1

TA的资源

一粒金砂(初级)

板凳
 
littleshrimp 发表于 2022-3-2 09:10 感谢分享,这个帖子写的很详细。

感谢分享,这个帖子写的很详细。目前还没有看到错误的地方!

此帖出自GD32 MCU论坛
 
 
 

回复

35

帖子

1

TA的资源

一粒金砂(中级)

4
 
littleshrimp 发表于 2022-3-2 09:10 感谢分享,这个帖子写的很详细。

此帖出自GD32 MCU论坛
 
 
 

回复

35

帖子

1

TA的资源

一粒金砂(中级)

5
 
yang1114 发表于 2022-3-2 10:07 感谢分享,这个帖子写的很详细。目前还没有看到错误的地方!

此帖出自GD32 MCU论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
未来计算机与计算机技术

未来计算机与计算机技术 计算机的关键技术继续发展,未来的计算机技术将向超高速、超小型、平行处理、智能化的方向发展。尽 ...

【献给初学者】一些关于DSP的问题和解答之系列(一)

一、时钟和电源问: DSP的电源设计和时钟设计应该特别注意哪些方面?外接晶振选用有源的好还是无源的好? 答:时钟一般使用晶 ...

Piccolo TMS320F28027PTT-48Pin评估板

acai1123赠送的Piccolo TMS320F28027PTT-48Pin评估板,谢谢acai1123,谢谢eeworld。 用摄像头拍了一下,效果不好,但是用 ...

表羡慕ArduinoNano啦,动手做LaunchPad Nano吧!

刚做完,不早了所以跳过吐槽、灌水、骗稿费的部分(稿费……汗),直接进入正题。 在羡慕ArduinoNano的小巧?MSP430也可以Nan ...

下载有好礼!罗姆带您学习电源设计应用小技巧

与传统的硅器件相比,碳化硅(SiC)器件由于拥有低导通电阻特性以及出色的高温、高频和高压性能,已经成为下一代低损耗半导体可 ...

今天520,作为理工科的男生,你们是如何给另一半惊喜的?

一年一度的表白日又来了,不管是对爱人、亲人、朋友还是同事,总有你今天相对他表达自己心里最想说的。作为理工科的你们,你们是 ...

仿真AWR学习网站

596235 细致到PCB与cadence

[HPM-DIY]littlevgl benchmark比分? 先楫hpm6750 or 意法stm32h747 winer?

本帖最后由 RCSN 于 2022-8-6 15:55 编辑 对比数据这种,其实也没啥必要,但是趋于好奇心,也搞个对比数据看看,需要说明的 ...

【得捷Follow me第3期】使用Xiao开发板给他过一个难忘的生日

本帖最后由 大波丁 于 2023-12-17 21:58 编辑 有幸入围本次的【Follow Me第三期】活动,从得捷DigiKey采购了以下物料: ...

家电补贴大家享受没?

本帖最后由 freebsder 于 2024-11-25 18:00 编辑 这波家电补贴蛮划得来,亲身体验。 周末给媳妇买了个笔记本,asus的1 ...

关闭
站长推荐上一条 1/10 下一条
有奖探索 | 和村田一起,深挖 GNSS 开发!
活动时间:即日起-5月11日
活动奖励:智能手环、螺丝刀套装、双肩包

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 12

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表