|
51hei團團 發(fā)表于 2021-2-28 23:44
干的漂亮,能分享下程序嗎?
/*
*32只WS2812+滾珠開關(guān)制作的搖搖棒*
*演示在上方16個LED上顯示“你真棒”三個漢字
*CPU:HC89S003F4 16K bytes flash ROM, 256+256 bytes data RAM
*WS2812 接P22(推挽驅(qū)動) ,滾珠開關(guān)接P00(下降沿中斷方式)
*晶振頻率:32MHz,F(xiàn)osc 16MHz
*程序版本:V1.00
*硬件平臺:003F4 V1.00
*編寫軟件:Keil uVision4
*編寫:xxd0708
*聲明:本程序只供學(xué)習(xí)使用,未經(jīng)作者許可,不得用于其它任何用途
*/
#define ALLOCATE_EXTERN
#include "HC89S003F4.h"
#include <intrins.h>
/**********************************************************
程序名稱:LED搖搖棒顯示64*16像素
簡要說明:外部中斷方式INT0顯示;取模方式:縱向取模、字節(jié)倒序
(取點方式:縱向8點上高位,字節(jié)排列:上到下左到右)
**********************************************************/
sbit WS2812_IO = P2^2 ;
u8 KY; //防止重影的控制變量
u8 cont_rock=0;
u8 cont_col=0;
u8 col_r,col_g,col_b;
// 你(0) 真(1) 棒(2)
code u8 dat_word1[]=
{
0x00,0x80,0x01,0x00,0x06,0x00,0x1F,0xFF,0xE0,0x00,0x02,0x08,0x04,0x30,0x18,0xC0,
0xF0,0x02,0x10,0x01,0x13,0xFE,0x10,0x00,0x10,0x80,0x14,0x60,0x18,0x18,0x00,0x00,/*"你",3*/
0x00,0x08,0x20,0x08,0x20,0x09,0x2F,0xFA,0x2A,0xAC,0x2A,0xA8,0x2A,0xA8,0xFA,0xA8,
0x2A,0xA8,0x2A,0xA8,0x2A,0xAC,0x2F,0xFA,0x20,0x09,0x20,0x08,0x00,0x08,0x00,0x00,/*"真",4*/
0x08,0x20,0x08,0xC0,0x0B,0x00,0xFF,0xFF,0x09,0x00,0x08,0x80,0x22,0x48,0x2A,0x88,
0x2B,0x28,0x2E,0x28,0xFA,0xFF,0x2A,0x28,0x2B,0x28,0x2A,0x88,0x22,0x48,0x00,0x00,/*"棒",5*/
};
//延時子函數(shù)-16Mhz 1ms延時
void delayMs_16Mhz(u16 ms)
{
u16 j;
for(; ms>0; ms--)
for(j=1596; j>0; j--);
}
//延時函數(shù)-16Mhz 1us延時
void delayUs_16Mhz(u8 us)
{
for(; us>0; us--)
{
_nop_();
_nop_();
_nop_();
}
}
void ws2812_rst(void)
{
WS2812_IO = 0;
delayUs_16Mhz(80);
}
void ws2812_write_byte( u8 dat)
{
u8 i = 8;
dat <<= 1; //最高位進入CY
while(i)
{
//高電平時間小于0.45uS為邏輯0,大于時為邏輯1
WS2812_IO = 1;
//如果主頻較高可在此處適當(dāng)增加_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
WS2812_IO = CY;
_nop_();
_nop_();
_nop_();
_nop_();
//如果主頻較高可在此處適當(dāng)增加_nop_();
WS2812_IO = 0; //位發(fā)送完保持低電平,時間不大于50us。否則復(fù)位
_nop_();
_nop_();
_nop_();
_nop_();
dat <<= 1; //最高位進入CY
i--;
}
}
/*顯示關(guān)閉*/
void display_off(void)
{
uchar i;
i=0;
while( i< 32 )
{
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
i++;
}
ws2812_rst();
}
/*顯示子程序 在上方16個LED上顯示三個漢字*/
void display_3word(void)
{
uchar i,j,temp;
//ws2812_rst();
i=0;
j=0;
while(j<96) //3個漢字3*16*2個字節(jié)
{
i=0;
while( i< 16 ) //下16不顯示 可修改
{
//與普通LED主要更改點,有顯示時發(fā)三個分量數(shù)據(jù),否則發(fā)三個0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
i++;
}
temp = dat_word1[j+1];//上方16位先送第二字節(jié)(依取模方式而定)
i=0;
while( i< 8 )
{
if(temp&0x01) //從低到高送顯示位(依取模方式而定)
{
//與普通LED主要更改點,有顯示時發(fā)三個分量數(shù)據(jù),否則發(fā)三個0
ws2812_write_byte( col_g);
ws2812_write_byte( col_r);
ws2812_write_byte( col_b);
}
else
{
//與普通LED主要更改點,有顯示時發(fā)三個分量數(shù)據(jù),否則發(fā)三個0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
}
i++;
temp = temp >>1; //下一位
}
temp = dat_word1[j]; //上方16位再送第一字節(jié)(依取模方式而定)
while( i< 16 )
{
if(temp&0x01) //從低到高送顯示位(依取模方式而定)
{
//與普通LED主要更改點,有顯示時發(fā)三個分量數(shù)據(jù),否則發(fā)三個0
ws2812_write_byte( col_g);
ws2812_write_byte( col_r);
ws2812_write_byte( col_b);
}
else
{
//與普通LED主要更改點,有顯示時發(fā)三個分量數(shù)據(jù),否則發(fā)三個0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
}
temp = temp >>1; //下一位
i++;
}
delayUs_16Mhz(200); //延時量自行調(diào)整,當(dāng)搖的速度一定時,延時越大,字越寬但能顯示字?jǐn)?shù)減少
j +=2; //漢字下一列
}
//發(fā)送完三個漢字后清屏
display_off();
}
/*中斷服務(wù)程序*/
void intersvr0(void) interrupt 0 using 1
{
//當(dāng)從右向左搖時,產(chǎn)生中斷,KY取反變?yōu)?,此時不顯示,不運行下面的語句
delayMs_16Mhz(10);
if(~P0^0)//10mS消抖
{
cont_rock ++; //判斷中斷次數(shù)
if(cont_rock >= 20)
cont_rock = 20;
//每個搖動來回滾珠開關(guān)會在擺幅兩端分別產(chǎn)生下降沿中斷,只提取其中一次
delayMs_16Mhz(30); //延時量改變首字顯示位置,越大越靠后
if((cont_rock&0x01) == 0) //偶數(shù)時顯示(或奇數(shù)次,依初值和開關(guān)方向而定)
{
display_3word();
}
else
{
display_off();
}
}
PINTF0 &= 0xFE;// HC89S003需軟件清標(biāo)志位INT0F
}
/**************************************************************************************
* @實現(xiàn)效果 將Fosc設(shè)置為16MHz,F(xiàn)cpu設(shè)置為16MHz
**************************************************************************************/
void main()
{
/************************************系統(tǒng)初始化****************************************/
WDTCCR = 0x00; //關(guān)閉看門狗
//本例程為方便測試關(guān)閉看門狗,實際使用中,建議客戶打開看門狗,詳見WDT復(fù)位例程
CLKSWR = 0x51; //選擇內(nèi)部高頻RC為系統(tǒng)時鐘,內(nèi)部高頻RC 2分頻,F(xiàn)osc=16MHz
CLKDIV = 0x01; //Fosc 1分頻得到Fcpu,F(xiàn)cpu=Fosc
/**********************************相關(guān)配置初始化**************************************/
P2M1 = P2M1&0xF0|0x08; //WS2812信號 P22設(shè)置為推挽輸出
P0M0 = P0M0&0xF0|0x06; //滾珠開關(guān)P00設(shè)置為帶施密特上拉輸入 (作為外部中斷)
P00DBC = 0xFF; //滾珠開關(guān)P00端口消抖,約250uS
PITS0 = PITS0&0xFC|0x01; //外部中斷0下降沿中斷
EX0=1; //開外部中斷
EA=1; //開總中斷
cont_col = 0; //顏色索引初值
display_off();
while(1) //主程序中只檢測按鍵
{
cont_rock = 0;
delayMs_16Mhz(1000);
if(cont_rock == 0) //檢測1秒內(nèi)搖擺次數(shù),如無則顏色回初值
{
cont_col = 0;
}
else
{
//顏色索引每秒加一改變一次顏色
if(cont_col >=5) //暫用6種顏色
{
cont_col = 0;
}
else
{
cont_col ++; //改變顏色
}
//按索引賦顯示顏色分量值
col_r = 0;
col_g = 0;
col_b = 0;
switch(cont_col)
{
case 0: col_r = 0x20;break;
case 1: col_g = 0x20;break;
case 2: col_b = 0x20;break;
case 3: col_r = 0x20;col_g = 0x20;break;
case 4: col_g = 0x20;col_b = 0x20;break;
case 5: col_b = 0x20;col_r = 0x20;break;
default: cont_col=0; col_r = 0x20;break;
}
}
}
}
|
評分
-
查看全部評分
|