📄 m8-spi-ds1302.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 + -