完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
谈到LED大家一定都不陌生,在玩开发板的时候就点亮过各种颜色的贴片LED了吧,可是当我们同时要用到多个LED的时候,芯片IO不够用了呢?对了,点下我的头像看一下查理复用算法,那如果依然不够用了咋办呢?
新道具出现了-略微昂贵的编码RGB-SK6812 当然可编码的LED不止这颗型号,类似有WS2812B这些型号,但控制原理如出一辙,要问我为啥原理相似,还不是生产厂家为了取代别家涨价的物料而做的咯,回归正题,具体控制原理我们先熟悉一下,如下图; 由图可以得到的信息: (1)编码是以24bit来完成一个LED的RGB效果,也就是如果需要点亮N个LED,则需要发送N个24bit数据,然后复位一下,就可以实现不同LED亮出不一样颜色的效果了 (2)每个bit的高低电平:cycle(周期)=1.2us,占空比=50%为1,占空比=30%为0 (3)编码LED是单线通信,到这里可以构思的方法出现了三种:1-SPI;2-IO;3-PWM 这里我不详细解说我实际操作时候遇到的问题,以及我是如何排除这些方法的,最后结果我选择了PWM+DMA的方式,原因是该方案既不浪费资源,且移植性强,可操作性强 正文 在MCU的选型中,确认是否具备PWM+DMA功能,如果不具备就可以不继续浪费时间了; 首先配置PWM,这里有一个功能,在我使用的MCU中是具备同时寄存两种PWM波形的,用户需要确认自己使用的MCU是否具备此功能,或者可以同时寄存更多种PWM波形。在初始化时将这两种波形先预存好; pwm_set_cycle_and_duty(PWM_ID,(uint8_t)(RGB_cycle_set),(uint8_t)(RGB_duty_high_value)); pwm_set_pwm0_shadow_cycle_and_duty(RGB_cycle_rest_set,RGB_duty_rest_low_value); /*每个MCU配置不同,不需要细纠*/ 然后预设好中断 pwm_set_interrupt_enable(PWM_IRQ_PWM0_IR_DMA_FIFO_DONE); irq_set_mask(FLD_IRQ_SW_PWM_EN); 此时不需要打开PWM输出,等到主函数中配置完需要输出的pwm组后再输出; 准备工作还没有结束,我们需要再单独配置一下底层代码处的输出高和输出低电平的驱动函数 /* * @description : 设置电平1的pwm * @param - none : 无 * @return - none : 无 */ uint16_t hal_set_pwm0_high(void) { return pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL, 1);//高脉冲生效,1个PWM0_PULSE_NORMAL帧 } /* * @description : 设置电平0的pwm * @param - none : 无 * @return - none : 无 */ uint16_t hal_set_pwm0_low(void) { return pwm_config_dma_fifo_waveform(1, PWM0_PULSE_SHADOW, 1);//高脉冲生效,1个PWM0_PULSE_SHADOW帧 } (内容根据自己的MCU提供的SDK包进行修改) 然后开始正式的驱动程序: /* * @description : 对DMA进行填充,单一色域的多个rgb亮 * @param - len : 要显示的灯数量 * @param - *rgb : 要显示的灯的三色参数数组 * @return - none : 无 */ void api_SK6812_send_dat_one_in(uint8_t *rgb, uint16_t len) { uint8_t i; uint8_t memaddr = 2; while (len) { for(i=0; i<8; i++) // GREEN data { IR_DMA_Buff[memaddr] = ((rgb[GREEN]< memaddr++; } for(i=0; i<8; i++) // RED { IR_DMA_Buff[memaddr] = ((rgb[RED]< memaddr++; } for(i=0; i<8; i++) // BLUE { IR_DMA_Buff[memaddr] = ((rgb[BLUE]< memaddr++; } } uint32_t length = memaddr*2 - 4; uint16_t *buff ; buff=IR_DMA_Buff; buff[0]= length&0xff; buff[1]= (length>>16)&0xff; SK6812_Show(); } 这是一个单一颜色的多个LED驱动的代码,简而言之就是使用逻辑将我们的数组数据填充到DMA数组中,然后驱动DMA,后面的功能也是如此,然后在外围通过改变数组的内容,实现各种想要的任务,例如呼吸,渐变色,炫光 思想就是这样的一个思想,实现任务还是建议各位自己动手尝试,如果实在不想,可以去我的文章的代码库里拿取 |
|
|
|
只有小组成员才能发言,加入小组>>
3263 浏览 9 评论
2944 浏览 16 评论
3443 浏览 1 评论
8955 浏览 16 评论
4036 浏览 18 评论
1081浏览 3评论
561浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
554浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2289浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1849浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-10 19:26 , Processed in 1.231534 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号