AVR单片机Atxmega128A3U点亮SK6812RGBW灯带显示程序
1、灯带数据格式和数位循序
2、LED码定义和时序
数据传输时间
时序表名称 Min. 实际值 Max. 单位
T 码元时间 1.2 -- -- us
T0H 0码,高电平时间 0.2 0.32 0.4 us
T0L 0码,低电平时间 0.8 -- -- us
T1H 1码,高电平时间 0.58 0.64 1.0 us
T1L 1码,低电平时间 0.2 -- -- us
Reset 复位码,低电平时间 >80 -- -- us
(1)协议采用单极性归零码,每个码元必须有低电平,本协议的每个码元起始为高电平,高电平时间宽度决定是“0”码还是“1”码;
(2)书写程序时,码元周期最低要求为1.2us;
(3)“0”码和“1”码的高电平时间按照上表的规定范围,“0”码和“1”码的低电平时间要求小于20us。
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(); //灯带复位
//发送数据顺序: g7g6g5g4g3g2g1g0r7r6r5r4r3r2r1r0b7b6b5b4b3b2b1b0
void send_data(unsigned char r, unsigned char g, unsigned char b,unsigned char w);
#endif
4、文件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_();
}
}
//发送数据顺序:
//g7g6g5g4g3g2g1g0r7r6r5r4r3r2r1r0b7b6b5b4b3b2b1b0w7w6w5w4w3w2w1w0
void 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 initialization
void system_clocks_init(void)
{
unsigned char n,s;
// Optimize for speed
#pragma optsize-
// Save interrupts enabled/disabled state
s=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 CLK
OSC.XOSCCTRL=OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
// Enable the external oscillator/clock source
OSC.CTRL|=OSC_XOSCEN_bm;
// Wait for the external oscillator to stabilize
while ((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 factor
n=(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 PLL
OSC.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 kHz
n=(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 stabilize
while ((OSC.STATUS & OSC_PLLRDY_bm)==0);
// Select the system clock source: Phase Locked Loop
n=(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 kHz
OSC.CTRL&= ~(OSC_RC2MEN_bm | OSC_RC32MEN_bm | OSC_RC32KEN_bm);
// Lock the CLK.CTRL and CLK.PSCTRL registers
n=CLK.LOCK | CLK_LOCK_bm;
CCP=CCP_IOREG_gc;
CLK.LOCK=n;
// ClkPer output disabled
PORTCFG.CLKEVOUT&= ~(PORTCFG_CLKOUTSEL_gm | PORTCFG_CLKOUT_gm);
// PLL fault detection: Off
// External clock source failure detection: On
n=(OSC.XOSCFAIL & (~(OSC_PLLFDEN_bm | OSC_XOSCFDEN_bm))) | OSC_XOSCFDEN_bm;
CCP=CCP_IOREG_gc;
OSC.XOSCFAIL=n;
// Restore interrupts enabled/disabled state
SREG=s;
// Restore optimization for size if needed
#pragma optsize_default
}
// Oscillator failure non-maskable interrupt
interrupt [OSC_OSCF_vect] 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 register
PORTF.OUT=0xff;
// Pin0: Input
// Pin1: Input
// Pin2: Output
// Pin3: Input
// Pin4: Input
// Pin5: Input
// Pin6: Input
// Pin7: Input
PORTF.DIR=0x04;
// Pin0 Output/Pull configuration: Totempole/PULLUP
// Pin0 Input/Sense configuration: Sense both edges
// Pin0 Inverted: Off
// Pin0 Slew Rate Limitation: Off
PORTF.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: Off
PORTF.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: Off
PORTF.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: Off
PORTF.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: Off
PORTF.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: Off
PORTF.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: Off
PORTF.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: Off
PORTF.PIN7CTRL=PORT_OPC_TOTEM_gc | PORT_ISC_BOTHEDGES_gc|PORT_OPC_PULLUP_gc;
// Interrupt 0 level: Disabled
// Interrupt 1 level: Disabled
PORTF.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: Off
PORTF.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: Off
PORTF.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 section
n=(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 scheduling
PMIC.INTPRI=0x00;
// Restore optimization for size if needed
#pragma optsize_default
//初始化PORT和System_Clock
system_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[i].red, rainbow[i].green, rainbow[i].blue,rainbow[i].white);
delay_ms(500);
ledstrap_reset();
}
}
} |