Liuweixing 发表于 2023-2-16 09:30

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();       }}}

Liuweixing 发表于 2023-2-21 15:29

这个程序适合没有中断程序打断发送函数的情形。如果要用单片级控制SK6812RGBW灯带,最好做个专门的单片机控制板,不用中断,或只有一个中断,这个中断用于定时,在这个中断程序中发送颜色数据。进入中断后,首先关闭全局中断,退出中断前,再打开全局中断。

zwsam 发表于 2023-11-1 09:07

页: [1]
查看完整版本: AVR单片机Atxmega128A3U点亮SK6812RGBW灯带显示程序