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

📄 m8-spi-ds1302.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
  //宏定义
  #define EnDS1302 PORTB|= (1<<2)	// 置CE为高电平,使能SPI接口
  #define DiDS1302 PORTB&=~(1<<2)	// 置CE为低电平,关闭SPI接口
 /***************************************************/
  void port_init();
  void delayms(uint k);
  void spi_init();
  uchar spi_send(uchar BYTE);
  uchar spi_receive();
  void uart();
  void sendstr(uchar *s);
  unsigned char time[7]={0x12,0x01,0x18,0x03,0x15,0x48,0x07};// 初始化时间 年 月 日 星期 时 分 秒		   
 /**************************************************/
  	uchar send_time[]="         ";//时、分、秒 的格式	     
	uchar send_riqi[]="         ";//年、月、日 的格式		  
	uchar send_xingqi[]="week:1";//星期 
	uchar timebuf[7]={0x55,0x32,0x12,0x02,0x15,0x01,0x12}; //秒,分,时 星期,日,月,年
  	void write_ds1302(unsigned char addr,unsigned char command);
    void read_ds1302(unsigned char addr);
	void initial_ds1302();
	void send_UART();
 /**************************************************/
  int main()
  {
   port_init();
   uart();
   sendstr("AVR-DS1302万年历");
   	sendstr(send_time);
	sendstr(send_riqi);
	sendstr(send_xingqi);
	send_UART();
 									//设定SPI接口
   spi_init();
   delayms(100);
   initial_ds1302();
   delayms(3000);
   while(1)
   {
	read_ds1302(0xbf);
	send_UART();
	delayms(4600);

   }
  }
 /***************************************************/
  void port_init()
  {
  DDRC=0xFF;
  PORTC=0x7e;
  DDRD=0XFF;
  PORTD=0xFf;
  DDRD=(1<<1);					//串口的输出

  }
 /*****************************************************/
  void spi_init()  //主机模式,高位先传输
  {
  
   PORTB|=~((1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5));	 //SS拉高,使AVR处于主机模式,同时用来控制DS1302的RST脚
    									//DS1302带内部下拉电阻
   DDRB|=(1<<PB2)|(1<<PB3)|(1<<PB5);	/* 设置SS输出,不影响SPI功能,可以用来控制从机控制脚,MOSI 和SCK 为输出,其他为输入 */
  
   //SPSR=1<<SPI2X;  //0X01
   SPCR = (1<<SPE) | (1<<MSTR)   //CPOL CPHA 00,SPI模式0,上升沿采样,下降沿设置完成。DORD=1,从LSB开始传输(低位),ds1302是从低位开始传送的
		  |(1<<DORD)|(1<<SPR0);	/* 使能SPI主机模式,设置时钟速率为fck/16   0X51*/
   
  }

/**********************************************************/
	void write_ds1302(unsigned char addr,unsigned char command)
   {
     unsigned char rdata;
     EnDS1302;		// 使能LCD
    _delay_us(10);
     spi_send(addr);
	_delay_us(10);
	spi_send(command);
    rdata=SPDR;							// 读取数据    DiDS1302;					       // 关断 SPI通讯
    _delay_us(10);
   }
/******************************************************/
   void read_ds1302(unsigned char addr)
   {
	uchar len=7;
    uchar *p,t=0;
     EnDS1302;		// 使能LCD
    _delay_us(5);
    SPDR=addr;
   	while (!(SPSR&(1<<SPIF)));	 /* 查询SPI中断位,等待传输结束 */
    _delay_us(4);	
    while (len--)
    {    	SPDR = *p++;			 		// 传送数据到SPI寄存器
      	while (!(SPSR&(1<<SPIF)));	 /* 查询SPI中断位,等待传输结束 */
    	timebuf[t++]=SPDR;						// 读取数据
	};
	DiDS1302;								// 关断SPI通讯
    _delay_us(10);
   }
/********************************************************/
   void initial_ds1302()
   {
   write_ds1302(0x8e,0x00);   //写保护寄存器,在对时钟或RAM写前WP一定要为0
   write_ds1302(0x8c,time[0]);   //年  
   write_ds1302(0x88,time[1]);   //月  
   write_ds1302(0x86,time[2]);   //日  
   write_ds1302(0x8A,time[3]);   //星期  
   write_ds1302(0x84,time[4]);   //时	  
   write_ds1302(0x82,time[5]);   //分	 
   write_ds1302(0x80,time[6]);   //秒	  
   write_ds1302(0x8e,0x80);   //写保护寄存器	
   }



/**************发送时间到串口***************************************/
   void send_UART()
   {
    send_time[0]=timebuf[2]/16+'0';
	send_time[1]=timebuf[2]%16+'0';
	send_time[3]=timebuf[1]/16+'0';
	send_time[4]=timebuf[1]%16+'0';
	send_time[6]=timebuf[0]/16+'0';
	send_time[7]=timebuf[0]%16+'0';

	send_riqi[0]=timebuf[6]/16+'0';
	send_riqi[1]=timebuf[6]%16+'0';
	send_riqi[3]=timebuf[4]/16+'0';
	send_riqi[4]=timebuf[4]%16+'0';
	send_riqi[6]=timebuf[3]/16+'0';
	send_riqi[7]=timebuf[3]%16+'0';

	send_xingqi[5]=timebuf[5]%16+'0';

	sendstr(send_time);
	sendstr(send_riqi);
	sendstr(send_xingqi);
   }
/******************************************************/
  uchar spi_send(uchar BYTE)
  {
  	SPDR = BYTE;   //装入数据寄存器  	/* 启动数据传输 */
	while (!(SPSR&(1<<SPIF)));	 /* 查询SPI中断位,等待传输结束 */
    return SPDR; //紧接着访问SPDR寄存器,会自动清0 中断标志位SPIF
  }

/**********************************************************/
  uchar spi_receive()  //spi自动读数据到寄存器中了。可以直接取出数据来
  {
	/* 等待接收结束 */
	while(!(SPSR&(1<<SPIF)));
	/* 返回数据 */
	return SPDR; //紧接着发送完毕就能返回接收数据,不用设置
  }

  /******************************************/
  void uart()   //特别注意写UCSRC时,要把最高位置1,否则写不进去
  {
    UCSRB  = 0x00;     //先不使能发送接收
    UCSRA  = 0x00;     //Bit1为1则倍速发送,这里不倍速
    UCSRC  = 0x86;   //8位数据格式,异步方式,URSEL=1时,写UCSRC寄存器
    UBRRL  = 25;     //波特率:9600 Bps 8MHZ时钟 51 1MHZ  6  2MHZ 12 4MHZ 25
    UBRRH  = 0x00;     //误差率:0.156%
    UCSRB  = 0x98;  //使能发送接收,使能接收中断
  }

    //-----------------------------------------------------------
	//串口接收字节子程序
	//-----------------------------------------------------------
	unsigned char Getchar(void)
	{
	   while(!(UCSRA& (1<<RXC)));
	   return UDR;
	}
  /******************************************/
  void sendstr(uchar *s)
  {
   while (*s)
   {
      while (!(UCSRA&(1<<UDRE)));
      UDR=*s;
      s++;
   }
   while (!(UCSRA&(1<<UDRE)));
      UDR=0x0a;   //回车换行
   while (!(UCSRA&(1<<UDRE)));
      UDR=0x0d;
  }
 /******************************************************/
 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 + -