⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi595点阵led.c

📁 AVR例子程序和protues仿真
💻 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 + -