打印
[AVR单片机]

AVR单片机Atxmega128A3U点亮SK6812RGBW灯带显示程序

[复制链接]
1102|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Liuweixing|  楼主 | 2023-2-16 09:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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
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
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;     //32RGBW颜色结构
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, Atxmega128A3UPORTF的引脚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
//初始化PORTSystem_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.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 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

61

帖子

0

粉丝