AVR单片机Atxmega128A3U点亮SK6812RGBW灯带显示程序
AVR单片机Atxmega128A3U点亮SK6812RGBW灯带显示程序1、灯带数据格式和数位循序file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml7376/wps1.jpg file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml7376/wps2.jpg file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml7376/wps3.jpg 2、LED码定义和时序file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml7376/wps4.jpg 数据传输时间时序表名称Min.实际值Max.单位
T码元时间1.2----us
T0H0码,高电平时间0.20.320.4us
T0L0码,低电平时间0.8----us
T1H1码,高电平时间0.580.641.0us
T1L1码,低电平时间0.2----us
Reset复位码,低电平时间>80----us
(1)协议采用单极性归零码,每个码元必须有低电平,本协议的每个码元起始为高电平,高电平时间宽度决定是“0”码还是“1”码;(2)书写程序时,码元周期最低要求为1.2us;(3)“0”码和“1”码的高电平时间按照上表的规定范围,“0”码和“1”码的低电平时间要求小于20us。file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml7376/wps5.jpg 3、文件ledstrap.h灯带输入信号引脚为PORTF.2#ifndef _LEDSTRAP_H_#define _LEDSTRAP_H_//灯带输出引脚控制#define LED_DO_HIGH (PORTF.OUTSET=0b00000100)//灯带数据引脚输出高电平PF2#define LED_DO_LOW (PORTF.OUTCLR=0b00000100)//灯带数据引脚输出低电平#define _nop_()#asm("NOP")#define COLOR_NUM 9 //显示9种颜色#define LIGHT_NUM 20 //可以亮20个灯。typedef struct color{ unsigned char red; unsigned char green; unsigned char blue; unsigned char white;} COLOR; //32位RGBW颜色结构 void ledstrap_reset();//灯带复位//发送数据顺序: g7g6g5g4g3g2g1g0r7r6r5r4r3r2r1r0b7b6b5b4b3b2b1b0void send_data(unsigned char r, unsigned char g,unsigned char b,unsigned char w); #endif4、文件ledstrap.c#include "xmega128a3u.h"#include "general.h"#include "ledstrap.h" //”0”码输出函数void code0() { LED_DO_HIGH; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); LED_DO_LOW; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();} //“1”码输出函数void code1() { LED_DO_HIGH; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); LED_DO_LOW; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); //_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}#define CODE0 code0();#define CODE1 code1();//>80μs void ledstrap_reset(){ unsigned int i; LED_DO_LOW;//Din = 0; for(i=0;i<80;i++) { _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_();_nop_(); }} //发送数据顺序: //g7g6g5g4g3g2g1g0r7r6r5r4r3r2r1r0b7b6b5b4b3b2b1b0w7w6w5w4w3w2w1w0void send_data(unsigned char r,unsigned char g,unsigned char b,unsigned char w){ unsigned char a; for(a=0;a<8;a++) { if(g&0x80) CODE1 else CODE0 g<<=1; } for(a=8;a<16;a++) { if(r&0x80) CODE1 else CODE0 r<<=1; } for(a=16;a<24;a++) { if(b&0x80) CODE1 else CODE0 b<<=1; } for(a=24;a<32;a++) { if(w&0x80) CODE1 else CODE0 w<<=1; }}5、演示函数AVR开发工具是:CodeVision3.12,初始化部分利用向导工具实现。 注意:本程序系统时钟是32MHz, Atxmega128A3U的PORTF的引脚2设置成输出,主程序如下:#include "delay.h"#include "ledstrap.h"// 定义几组颜色COLOR rainbow[] = { {0xFF, 0x00, 0x00,0x00}, // red {0x00, 0xFF, 0x00,0x00}, //green {0x00, 0x00, 0xFF,0x00}, //blue {10,108,169,0}, //青蓝色 {0xFF, 0xFF, 0x00,0x00}, //yellow {0xFF, 0x00, 0xFF,0x00}, // violet {0, 0, 0xFF,0x7F}, // indigo {0x8B, 0, 0xFF,0x00}, // oringe {0, 0, 0,0}, // off};//下面是系统时钟初始化程序,采用外部16M晶振,通过锁相环2倍频输出32MHz时钟// System Clocks initializationvoid system_clocks_init(void){unsigned char n,s; // Optimize for speed#pragma optsize-// Save interrupts enabled/disabled states=SREG;// Disable interrupts#asm("cli") // External 16000.000 kHz oscillator initialization// Crystal oscillator increased drive current: Off// External Clock Source - Startup Time: 0.4-16 MHz Quartz Crystal - 16k CLKOSC.XOSCCTRL=OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;// Enable the external oscillator/clock sourceOSC.CTRL|=OSC_XOSCEN_bm; // Wait for the external oscillator to stabilizewhile ((OSC.STATUS & OSC_XOSCRDY_bm)==0); // PLL initialization// PLL clock source: External Osc. or Clock// PLL multiplication factor: 2// PLL output/2: Off// PLL frequency: 32.000000 MHz// Set the PLL clock source and multiplication factorn=(OSC.PLLCTRL & (~(OSC_PLLSRC_gm | OSC_PLLDIV_bm | OSC_PLLFAC_gm))) | OSC_PLLSRC_XOSC_gc | (0<<OSC_PLLDIV_bp) | 2;CCP=CCP_IOREG_gc;OSC.PLLCTRL=n;// Enable the PLLOSC.CTRL|=OSC_PLLEN_bm; // System Clock prescaler A division factor: 1// System Clock prescalers B & C division factors: B:1, C:1// ClkPer4: 32000.000 kHz// ClkPer2: 32000.000 kHz// ClkPer:32000.000 kHz// ClkCPU:32000.000 kHzn=(CLK.PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm))) | CLK_PSADIV_1_gc | CLK_PSBCDIV_1_1_gc;CCP=CCP_IOREG_gc;CLK.PSCTRL=n; // Wait for the PLL to stabilizewhile ((OSC.STATUS & OSC_PLLRDY_bm)==0); // Select the system clock source: Phase Locked Loopn=(CLK.CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_PLL_gc;CCP=CCP_IOREG_gc;CLK.CTRL=n; // Disable the unused oscillators: 2 MHz, 32 MHz, internal 32 kHzOSC.CTRL&= ~(OSC_RC2MEN_bm | OSC_RC32MEN_bm | OSC_RC32KEN_bm); // Lock the CLK.CTRL and CLK.PSCTRL registersn=CLK.LOCK | CLK_LOCK_bm;CCP=CCP_IOREG_gc;CLK.LOCK=n; // ClkPer output disabledPORTCFG.CLKEVOUT&= ~(PORTCFG_CLKOUTSEL_gm | PORTCFG_CLKOUT_gm);// PLL fault detection: Off// External clock source failure detection: Onn=(OSC.XOSCFAIL & (~(OSC_PLLFDEN_bm | OSC_XOSCFDEN_bm))) | OSC_XOSCFDEN_bm;CCP=CCP_IOREG_gc;OSC.XOSCFAIL=n; // Restore interrupts enabled/disabled stateSREG=s;// Restore optimization for size if needed#pragma optsize_default} // Oscillator failure non-maskable interruptinterrupt void oscillator_failure_isr(void){if (OSC.XOSCFAIL & OSC_XOSCFDIF_bm) { // External clock source failure detected // Clear the failure detection interrupt flag OSC.XOSCFAIL|=OSC_XOSCFDIF_bm; // Write your code here }}// 下面是初始化端口,只列出PORTF的初始化部分void ports_init(void){// PORTF initialization// OUT registerPORTF.OUT=0xff;// Pin0: Input// Pin1: Input// Pin2: Output// Pin3: Input// Pin4: Input// Pin5: Input// Pin6: Input// Pin7: InputPORTF.DIR=0x04;// Pin0 Output/Pull configuration: Totempole/PULLUP// Pin0 Input/Sense configuration: Sense both edges// Pin0 Inverted: Off// Pin0 Slew Rate Limitation: OffPORTF.PIN0CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin1 Output/Pull configuration: Totempole/PULLUP// Pin1 Input/Sense configuration: Sense both edges// Pin1 Inverted: Off// Pin1 Slew Rate Limitation: OffPORTF.PIN1CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin2 Output/Pull configuration: Totempole/PULLUP// Pin2 Input/Sense configuration: Sense both edges// Pin2 Inverted: Off// Pin2 Slew Rate Limitation: OffPORTF.PIN2CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin3 Output/Pull configuration: Totempole/PULLUP// Pin3 Input/Sense configuration: Sense both edges// Pin3 Inverted: Off// Pin3 Slew Rate Limitation: OffPORTF.PIN3CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin4 Output/Pull configuration: Totempole/PULLUP// Pin4 Input/Sense configuration: Sense both edges// Pin4 Inverted: Off// Pin4 Slew Rate Limitation: OffPORTF.PIN4CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin5 Output/Pull configuration: Totempole/PULLUP// Pin5 Input/Sense configuration: Sense both edges// Pin5 Inverted: Off// Pin5 Slew Rate Limitation: OffPORTF.PIN5CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin6 Output/Pull configuration: Totempole/PULLUP// Pin6 Input/Sense configuration: Sense both edges// Pin6 Inverted: Off// Pin6 Slew Rate Limitation: OffPORTF.PIN6CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Pin7 Output/Pull configuration: Totempole/PULLUP// Pin7 Input/Sense configuration: Sense both edges// Pin7 Inverted: Off// Pin7 Slew Rate Limitation: OffPORTF.PIN7CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;// Interrupt 0 level: Disabled// Interrupt 1 level: DisabledPORTF.INTCTRL=(PORTF.INTCTRL & (~(PORT_INT1LVL_gm | PORT_INT0LVL_gm))) | PORT_INT1LVL_OFF_gc | PORT_INT0LVL_OFF_gc;// Pin0 Pin Change interrupt 0: Off// Pin1 Pin Change interrupt 0: Off// Pin2 Pin Change interrupt 0: Off// Pin3 Pin Change interrupt 0: Off// Pin4 Pin Change interrupt 0: Off// Pin5 Pin Change interrupt 0: Off// Pin6 Pin Change interrupt 0: Off// Pin7 Pin Change interrupt 0: OffPORTF.INT0MASK=0x00;// Pin0 Pin Change interrupt 1: Off// Pin1 Pin Change interrupt 1: Off// Pin2 Pin Change interrupt 1: Off// Pin3 Pin Change interrupt 1: Off// Pin4 Pin Change interrupt 1: Off// Pin5 Pin Change interrupt 1: Off// Pin6 Pin Change interrupt 1: Off// Pin7 Pin Change interrupt 1: OffPORTF.INT1MASK=0x00;}//主程序函数void main(){unsigned char n;int i,j,k;#pragma optsize-// Make sure the interrupts are disabled#asm("cli")// Low level interrupt: On// Round-robin scheduling for low level interrupt: On// Medium level interrupt: On// High level interrupt: On// The interrupt vectors will be placed at the start of the Application FLASH sectionn=(PMIC.CTRL & (~(PMIC_RREN_bm | PMIC_IVSEL_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm))) | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm|PMIC_RREN_bm;CCP=CCP_IOREG_gc;PMIC.CTRL=n;// Set the default priority for round-robin schedulingPMIC.INTPRI=0x00;// Restore optimization for size if needed#pragma optsize_default//初始化PORT和System_Clocksystem_clocks_init();ports_init();//测试灯带:20个灯珠同种颜色循环100次K=0;while (k++<100){ for(i = 0;i<COLOR_NUM ; i++) { // 1. lighten all the lights for(j = 0; j < LIGHT_NUM; j++) send_data(rainbow.red, rainbow.green, rainbow.blue,rainbow.white); delay_ms(500); ledstrap_reset(); }}}
这个程序适合没有中断程序打断发送函数的情形。如果要用单片级控制SK6812RGBW灯带,最好做个专门的单片机控制板,不用中断,或只有一个中断,这个中断用于定时,在这个中断程序中发送颜色数据。进入中断后,首先关闭全局中断,退出中断前,再打开全局中断。
页:
[1]