[PIC®/AVR®/dsPIC®产品]使用MCC配置SPI硬件驱动WS2812B灯环

关于MCC提速的问题查看下面连接的帖子
教你如何解决MPLAB X IDE的MCC加载慢问题 - Microchip论坛 - PIC单片机论坛 - Microchip(微芯科技)MCU官方技术支持论坛 - 21ic电子技术开发论坛
接下来一步一步从新建工程讲起
1、新建工程
 


2、选择MCC Melody
 


3、选择本次要使用的设备资源SPI_Host和DELAY
 


4、接下来对时钟进行配置,将SPI时钟速率设置为8MHz
 

 点击左边Project Resources中的System下的Clock Control,右边会弹出上面界面选项卡,将Clock Source设置为HFINTOSC。
HF Internal Clock 选择为16Mhz,这样可以方便分频出8MHz,
Clock Divider 设置为1,主系统时钟不分频
点击左边Project Resources中的Drivers下的SPI_Host,在右边的设置选项卡做如下图中的设置,将Requested Speed(kHz)设置为8000
即设置到了8Mhz。这样脉宽的最小单位就是0.125us了。
[attach]2281912[/attach]
5、接下来需要对IO选择,由哪个IO接口输出SPI数据。引脚的选择是有讲究的,不可随意指定引脚使用,首先你要确定该引脚是否被其他功能占用,这个要根据你的板子上的设计来看,如果是全新的设计,那么选择会更加自有一些。
这里要打开芯片的用户手册,找到引脚分配表一章节,本次要使用的是SPI,另外根据选择的元件封装找到对应的表格。
 


 


我们注意到这些备注为1的引脚的默认功能是指定了的,根据备注,可知这是一个可重新映射的PPS输入信号。输入函数可以从显示的默认位置移动到其他几个PORTx引脚之一。
其他横线的引脚为备注2的,在这些行中显示的所有数字输出信号都是PPS可重新映射的。这些信号可以映射到输出到几个PORTx引脚选项之一。我使用的是PIC18F16QQ41-CNANO开发板,因此应按照该开发板原理图,找到合适没有被占用的引脚来使用,我使用的引脚配置如下图所示:

 


6、驱动原理
要知道驱动原理,需要先知道WS2812B的驱动时序
 


每一个LED由24BIT数据驱动
 


数据的时序波形如下图所示
 


数据参数的定义
 


LED 灯珠主要根据高电平时间判断“0”码和“1”码。
高电平时间介于 200ns~410ns,IC 判断为“0”码,高电平时间介于 640ns~1000ns,判断为“1”码。
“0”码和“1”码的低电平代表此码结束,准备接收下一数据码。
由于我们配置的SPI时钟为8MHz,那么每一个脉宽为0.125us
对于“0”码的高电平时间,2个脉宽为0.25us即可满足要求,因此我们用具备2个脉宽高电平的数据表示0,这个数据就是:0xC0
对于“1”码的高电平时间,6个脉宽为0.75us即可满足要求,因此我们用具备6个脉宽高电平的数据表示1,这个数据就是:0xFC
明白了这个原理,就可以编写代码了。
7、代码编写

复制

typedef struct COLOR

{

    uint8_t redChannel;

    uint8_t greenChannel;

    uint8_t blueChannel;

} color_t;



void ws2812_send(unsigned char x)

{

    for(int i=0;i<8;i++)

    {

        x<<=i;

        if(x&0x80)

        {

            SPI1_ByteWrite(0xFC);

            while(SPI1_IsTxReady()==false);

        }

        else

        {

            SPI1_ByteWrite(0xC0); 

            while(SPI1_IsTxReady()==false);

        }

    }

}



void WriteNeopixel(color_t const color)

{

    ws2812_send(color.greenChannel);    

    ws2812_send(color.redChannel);    

    ws2812_send(color.blueChannel);

}

另外我们只使用SDO的发送数据功能,因此我们要对函数SPI1_ByteWrite进行修改一下。
找到spi1.c文件
将函数修改为

复制

void SPI1_ByteWrite(uint8_t byteData)

{        

        SPI1CON2 = (SPI1CON2 & ~(_SPI1CON2_SPI1RXR_MASK)) | (_SPI1CON2_SPI1TXR_MASK);

        SPI1TCNTL = 1;

        //Write input data to SPI transmit buffer register

        SPI1TXB = byteData;

}

即对SPI1CON2只设置为发送模式。
然后在main函数就可以使用上述函数对灯珠进行控制了。

复制


#include "mcc_generated_files/system/system.h"

#include"mcc_generated_files/timer/delay.h"



#include"ws2812b.h"





//显示缓存,所有的变化操作都在这个数组进行

long led_buff_temp[20]={0};



/*

    Main application

*/

color_t neopixelsBuffer[20] = {



    { 64, 100, 64 }, { 64, 64,  0 }, {  0, 64, 64 }, {  0, 64,  0 },



    { 64,  0, 64 }, { 64,  0,  0 }, {  0,  0, 64 }, {  30,  10,  2 },



    { 96, 96, 96 }, { 48, 48, 48 }, { 24, 24, 24 }, { 12, 24, 12 },



    {  36,  36,  6 }, {  3,  33,  33 }, {  16,  16,  1 }, {  50,  0,  0 },



    {  6,  60,  6 }, {  3,  3,  30 }, {  10,  1,  10 }, {  0,  10,  0 }



};

color_t temp_led;



int main(void)

{

    SYSTEM_Initialize();

    // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts 

    // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts 

    // Use the following macros to: 



    // Enable the Global Interrupts 

    //INTERRUPT_GlobalInterruptEnable(); 



    // Disable the Global Interrupts 

    //INTERRUPT_GlobalInterruptDisable(); 

    SPI1_Open(HOST_CONFIG);

//点亮

    for(int i=0;i<20;i++) WriteNeopixel(neopixelsBuffer[i]);

//色彩滚动    





    while(1)

    {

        temp_led.blueChannel =neopixelsBuffer[0].blueChannel;

        temp_led.greenChannel=neopixelsBuffer[0].greenChannel;

        temp_led.redChannel  =neopixelsBuffer[0].redChannel;

        for(int i=0;i<19;i++)

        {

            neopixelsBuffer[i].blueChannel=neopixelsBuffer[i+1].blueChannel;

            neopixelsBuffer[i].greenChannel=neopixelsBuffer[i+1].greenChannel;

            neopixelsBuffer[i].redChannel=neopixelsBuffer[i+1].redChannel;

        }

        neopixelsBuffer[19].blueChannel =temp_led.blueChannel;

        neopixelsBuffer[19].greenChannel=temp_led.greenChannel;

        neopixelsBuffer[19].redChannel  =temp_led.redChannel;    

        DELAY_milliseconds(500);

        for(int i=0;i<20;i++) WriteNeopixel(neopixelsBuffer[i]);

    }    

}

烧录程序,可以看到灯环上的20个彩色LED颜色滚动起来了。子
---------------------
作者:gaoyang9992006
链接:https://bbs.21ic.com/icview-3393678-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值