📄 spi595点阵led.c
字号:
/**********************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#define uchar unsigned char
#define uint unsigned int
//宏定义
/***************************************************************************************/
void port_init();
void delayms(uint k);
void spi_init();
uchar spi_send(uchar BYTE);
void heng_sao();
void you_yi();
void zuo_yi();
void xia_yi();
void shang_yi();
void dui_xian();
void zhong_fen();
/************************************************************************************/
unsigned char disp[10][32] =
{
{0x20,0x00,0x17,0xFE,0x10,0x08,0x00,0x08,0x88,0x08,0x4B,0xC8,0x52,0x48,0x12,0x48,
0x22,0x48,0x23,0xC8,0xE2,0x48,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x28,0x20,0x10},/*"河",0*/
{0x04,0x40,0x04,0x40,0x04,0x40,0x04,0x44,0x04,0x4E,0x7C,0x58,0x04,0x60,0x04,0x40,
0x04,0x40,0x04,0x40,0x0C,0x40,0x34,0x42,0xE4,0x42,0x44,0x42,0x04,0x3E,0x00,0x00},/*"北",1*/
{0x00,0x00,0x7F,0xFE,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x10,0x80,0x10,0xFC,
0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0xFF,0xFE,0x00,0x00,0x00,0x00},/*"正",2*/
{0x02,0x00,0x01,0x00,0x3F,0xFE,0x20,0x04,0x40,0x08,0x1F,0xF0,0x01,0x00,0x11,0x00,
0x11,0x00,0x11,0xF0,0x11,0x00,0x29,0x00,0x25,0x00,0x43,0x00,0x81,0xFC,0x00,0x00},/*"定",3*/
{0x00,0x80,0x00,0x80,0xFC,0x80,0x05,0xFE,0x85,0x04,0x4A,0x48,0x28,0x40,0x10,0x40,
0x18,0x40,0x18,0x60,0x24,0xA0,0x24,0x90,0x41,0x18,0x86,0x0E,0x38,0x04,0x00,0x00},/*"欢",4*/
{0x40,0x00,0x21,0x80,0x36,0x7C,0x24,0x44,0x04,0x44,0x04,0x44,0xE4,0x44,0x24,0x44,
0x25,0x44,0x26,0x54,0x24,0x48,0x20,0x40,0x20,0x40,0x50,0x00,0x8F,0xFE,0x00,0x00},/*"迎",5*/
{0x08,0x00,0x09,0x00,0x11,0xFE,0x12,0x04,0x34,0x40,0x32,0x50,0x52,0x48,0x94,0x44,
0x11,0x44,0x10,0x80,0x00,0x00,0x29,0x04,0x28,0x92,0x68,0x12,0x07,0xF0,0x00,0x00},/*"您",6*/
{0x01,0x00,0x01,0x00,0x01,0x20,0x09,0x10,0x0D,0x0C,0x09,0x08,0x11,0x00,0x21,0x08,
0x41,0x0C,0x01,0x18,0x00,0x30,0x00,0x60,0x01,0x80,0x0E,0x00,0x70,0x00,0x00,0x00},/*"少",7*/
{0x02,0x00,0x02,0x00,0x02,0x00,0x03,0xFC,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xF0,
0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x20,0x10,0x00,0x00},/*"占",8*/
{0x08,0x00,0x0F,0xE0,0x08,0x20,0x10,0x40,0x1F,0xF8,0x31,0x08,0x51,0x08,0x11,0x08,
0x1F,0xF8,0x11,0x08,0x11,0x08,0x1F,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00},/*"鱼",9*/
};
/************************************************************************************/
int main()
{
port_init();
spi_init(); //设定SPI接口
//delayms(1000);
while(1)
{
heng_sao();
xia_yi();
shang_yi();
zuo_yi();
you_yi();
dui_xian();
zhong_fen();
}
}
/***************************************************/
void port_init()
{
DDRC=0xFF;
PORTC=0xFF;
DDRD=0XFF;
PORTD=0xFf;
}
/*****************************************************/
void spi_init() //主机模式,高位先传输
{
PORTB|=~((1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5)); //SS拉高,使AVR处于主机模式,同时用来控制DS1302的RST脚
//DS1302带内部下拉电阻
DDRB|=(1<<PB0)|(1<<PB2)|(1<<PB3)|(1<<PB5); /* 设置SS输出,不影响SPI功能,可以用来控制从机控制脚,MOSI 和SCK 为输出,其他为输入 */
SPCR = (1<<SPE)|(1<<MSTR) //CPOL CPHA 00,SPI模式0,上升沿采样,下降沿设置完成。DORD=1,先传数据的bit0位,注意595是从Q0向Q7移动数据的
|(1<<DORD)|(1<<SPR0); /* 使能SPI主机模式,设置时钟速率为fck/16 0X51*/
}
/************正常从上向下行扫**********************************/
void heng_sao()
{
uchar i,k;
for(i=0;i<16;i++)
{
for(k=10;k>0;k--)
{
spi_send(disp[k-1][2*i+1]);
spi_send(disp[k-1][2*i]);
}
PORTC=i;
delayms(22);
PORTC=0x10;
}
}
/*********右移显示就是左边字符逐渐增加,右边空区逐渐减少********/
void you_yi() //
{
uchar i,k,t,j;
for(t=10;t>0;t--)
{
for(i=0;i<16;i++)
{
for(k=0;k<(t-1);k++) //先把空字符移到右边不显示区
{
spi_send(disp[k][2*i+1]&0x00);
spi_send(disp[k][2*i]&0x00);
}
for(j=10;j>(t-1);j--) //再移要显示的字符
{
spi_send(disp[j-1][2*i+1]);
spi_send(disp[j-1][2*i]);
}
PORTC=i;
delayms(7);
PORTC=0x10;
} //end for(16)
} //end for(10)
delayms(1800);
}
/***********左移就是左边空区逐渐较少,右边字符逐渐增加*************************/
void zuo_yi()
{
uchar i,k,t,j;
for(t=1;t<11;t++) //移动显示t个汉字
{
for(i=0;i<16;i++)
{
for(j=t;j>0;j--) //先移动要显示的到右边
{
spi_send(disp[j-1][2*i+1]);
spi_send(disp[j-1][2*i]);
}
for(k=0;k<(10-t);k++) //再移空字符到左边
{
spi_send(disp[k][2*i+1]&0x00);
spi_send(disp[k][2*i]&0x00);
}
PORTC=i;
delayms(7);
PORTC=0x10;
} //end for(16)
} //end for(10)
delayms(1800);
}
/************字体向下移入显示******************************/
void xia_yi()
{
uchar i,k,j,temp;
for(j=0;j<16;j++) //下移有16种不同的状态,每种状态扫描一遍,行扫,每遍16次
{
temp=2*(16-j);
for(i=0;i<16;i++) //横扫,从第一行开始
{
if(temp<33) //控制有效显示行数,每个状态有效显示行数是递增的
{
for(k=10;k>0;k--)
{
spi_send(disp[k-1][temp-1]);
spi_send(disp[k-1][temp-2]);
}
temp+=2; //temp是一次性变化的,所以,上面对数据的填充也是一次性,对应行扫描16次就不会重复出现
}
PORTC=i;
delayms(9);
PORTC=0x10;
} //end for 行扫
} //end for 16状态
}
/*************字体向上移入显示*************************/
void shang_yi()
{
uchar i,k,j;
uchar temp=0; //特别注意这里temp,不能用unsigned int 下面减小过0后还会是个很大的正整数,改进:下面加个最大值判断就可以了
for(j=0;j<16;j++) //下移有16种不同的状态,每种状态扫描一遍,行扫,每遍16次
{
temp=2*j+1;
for(i=0;i<16;i++) //横扫,从最末行开始,这样下面数据的填充方便,因为显示是上移的,所以先填充数据没事,否则要显示完空白区才能填充
{
if(temp>=1&&(temp<32))
{
for(k=10;k>0;k--)
{
spi_send(disp[k-1][temp]);
spi_send(disp[k-1][temp-1]);
}
temp-=2; //用减法,先填充末行,扫一行,少填充一行数据,而且本来数据就是下行的数组坐标大于上行坐标,扫描又是从末行开始的,
}
PORTC=15-i; //从末行开始扫描,由于先显示的是数组的大坐标数据,所以先填充大数组,随便行扫上移,填充数组也减小
delayms(9);
PORTC=0x10;
} //end for 行扫
} //end for 16状态
}
/************由两侧逐渐向中间显示*********************************/
void dui_xian()
{
uchar i,k,t,j,s;
for(t=1;t<6;t++) //移动显示t个汉字
{
for(i=0;i<16;i++)
{
s=9;
for(j=t;j>0;j--) //先移动最右边要显示的数据
{
spi_send(disp[s][2*i+1]);
spi_send(disp[s][2*i]);
s--;
}
for(k=0;k<(10-2*t);k++) //再移空字符到中间
{
spi_send(0x00);
spi_send(0x00);
}
s=t-1;
for(j=t;j>0;j--) //再移动左边要显示的数据
{
spi_send(disp[s][2*i+1]);
spi_send(disp[s][2*i]);
s--;
}
PORTC=i;
delayms(17);
PORTC=0x10;
} //end for(16)
} //end for(10)
delayms(1800);
}
/*********从中间向左右逐渐消失**************************/
void zhong_fen()
{
uchar i,k,t,j,s;
for(t=5;t>0;t--) //移动显示t个汉字
{
for(i=0;i<16;i++)
{
s=9;
for(j=t;j>0;j--) //先移动最右边要显示的数据
{
spi_send(disp[s][2*i+1]);
spi_send(disp[s][2*i]);
s--;
}
for(k=0;k<(10-2*t);k++) //再移空字符到中间
{
spi_send(0x00);
spi_send(0x00);
}
s=t-1;
for(j=t;j>0;j--) //再移动左边要显示的数据
{
spi_send(disp[s][2*i+1]);
spi_send(disp[s][2*i]);
s--;
}
PORTC=i;
delayms(17);
PORTC=0x10;
} //end for(16)
} //end for(10)
delayms(1800);
}
/******************************************************/
uchar spi_send(uchar BYTE)
{
PORTB|=1<<PB2;
SPDR = BYTE; //装入数据寄存器 /* 启动数据传输 */
while (!(SPSR&(1<<SPIF))); /* 查询SPI中断位,等待传输结束 */
return SPDR; //紧接着访问SPDR寄存器,会自动清0 中断标志位SPIF
}
/******************************************************/
void delayms(uint k)
{
uint i,j;
for(i=0;i<k;i++)
{
for(j=0;j<100;j++)
{;}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -