DS1302程序读不出数据SPI通信,帮忙看一下那地方不对呢?
#include <iom16v.h>#include <macros.h>
#define uint unsigned int
#define uchar unsigned char
#define RS_0 PORTD&0xfe
#define RS_1 PORTD|0x01
#define E_0PORTD&0xfd
#define E_1PORTD|0x02
#define RW_0 PORTD&0xfb
#define RW_1 PORTD|0x04
/*读写控制*/
#define cmd_read 0x01
#define cmd_write 0x00
/*时钟日期命令*/
#define cmd_second 0x80
#define cmd_minute 0x82
#define cmd_hour 0x84
#define cmd_day 0x86
#define cmd_month 0x88
#define cmd_week 0x8a
#define cmd_year 0x8c
#define cmd_control 0x8e
//写保护
#define cmd_trickle_charge0x90
//充电控制
#define cmd_clocl_burst 0xbe
//连续写
/*时钟配置位*/
#define clock_halt 0x80
#define _12-24_slect 0x80
#define AM_PM_slect 0x20
#define protect 0x80
#define unprotect 0x00
/*充电控制*/
#define CFG_TC_D1R2 0xA5 //high 1 Diode +2K Resistors
#define CFG_TC_D2R8 0xAB //low2 Diodes+8K Resistors
#define CFG_TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00
/*RAM命令*/
#define cmd_RAM_base 0xc0
#define cmd_RAM_burst 0xfe
/*管脚定义*/
#define CE 4
#define MOSI 5
#define MISO 6
#define SCK 7
#define DS1302_ON PORTB|=(1<<4)
//使能DS1302
#define DS1302_OFF PORTB&=~(1<<4)
//关闭DS1302
uchar CURDATE;
uchar Timer={0,0};
uchar DS1302_EXIST;
uchar table={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
uchar DATA={0,0,0,0};
uchar init_data={0x50,0x59,0x23,0x06,0x10,0x04,0x05,0x80};
/*************************************************************************************/
void delay(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
{
for(j=1141;j!=0;j--)
{;}
}
}
/****************************************************************************************/
void init_SPI(void) //初始化SPI
{
SPCR=(1<<SPIE)|(1<<MSTR)|(1<<DORD)|(1<<SPR0);
}
/****************************************************************************************/
uchar Write_data_DS1302(uchar command,uchar wdata)//<------向DS1302读写数据
{
uchar rdata;
DS1302_ON;
delay(10);
SPDR=command;
while(!(SPSR&(1<<SPIF)));
delay(10);
SPDR=wdata;
while(!(SPSR&(1<<SPIF)));
rdata=SPDR;
DS1302_OFF;
return rdata;
}
/*******************************************************************************************/
void Burst_data(uchar CMD,uchar len,uchar *pwdata,uchar *prdata) //<-----读写一批数据到DS1302
{
DS1302_ON;
delay(10);
SPDR=CMD;
while(!(SPSR&(1<<SPIF)));
delay(10);
while(len--)
{
SPDR=*pwdata++;
while(!(SPSR&(1<<SPIF)));
*prdata++=SPDR;
}
DS1302_OFF;
delay(10);
}
/************************************************************************************/
uchar check_RTC(void) //<---------------检测DS1302
{
uchar i;
Write_data_DS1302(cmd_control|cmd_write,unprotect);
Write_data_DS1302(cmd_RAM_base|cmd_write,0xA5);
Write_data_DS1302(cmd_control|cmd_write,protect);
i=Write_data_DS1302(cmd_RAM_base|cmd_read,0x00);
if(i==0xA5)return 1;
else return 0;
}
/***************************************************************************************/
void init_RTC(void) //<----------------初始化DS1302
{
uchar temp;
Write_data_DS1302(cmd_control|cmd_write,unprotect);
Burst_data(cmd_clocl_burst|cmd_write,8,&init_data,&temp);
Write_data_DS1302(cmd_trickle_charge|cmd_write,0xA5);
Write_data_DS1302(cmd_control|cmd_write,protect);
}
/**************************************************************************************/
void BCD_to_ASCII(uchar cBCD,uchar *pstr)
{
uchar i,j;
i=cBCD>>4;
j=cBCD&0x0f;
*pstr++=i+0x30;
*pstr=j+0x30;
}
/*************************************************************************************
void decodeWEEK(uchar WEEK,uchar *pstr)
{
uchar i;
i=WEEK;
i&=0x07;
i=i<<1;
*pstr++=sWEEK;
*pstr=sWEEK;
}
/*****************************************************************************/
void read_date(void)
{
Burst_data(cmd_clocl_burst|cmd_read,7,0,CURDATE); //读取当前时间
BCD_to_ASCII(CURDATE,&Timer); //分 ,00~59
BCD_to_ASCII(CURDATE,&Timer); //秒 ,00~59
}
void display(uchar *p)
{
uchar i;
uchar sel=0x01;
for(i=0;i<4;i++)
{
PORTC=sel;
PORTD=table];
delay(2);
sel=sel<<1;
}
}
/**************************************************************************************/
void process(uchar *p1,uchar *p2)
{
p2=p1/10;
p2=p1%10;
p2=p1/10;
p2=p1%10;
}
/****************************************************************************************/
void main(void)
{
DDRC=0xff;
PORTC=0xff;
DDRD=0xff;
PORTD=0xff;
DDRB =(1<<4)|(1<<7)|(1<<6);
PORTB=~((1<<4)|(1<<5)|(1<<6)|(1<<7));
init_SPI();
delay(100);
init_RTC();
delay(500);
while(1)
{
read_date();
process(Timer,DATA);
display(DATA);
}
} DS1302不是SPI。 DS1302不可以用SPI方式通讯吗?不会吧?
http://cache.amobbs.com/bbs_upload782111/files_27/ourdev_535286.jpg
原理图 (原文件名:TP 第一次看到这么接SPI的
ds1302是用IO口模拟的通信时序,记得时序和SPI还是有区别的
SPI是数据进出各一条线,再加一条时钟线,单向传输
而1302的数据口是双向的
楼主打电话或发个电邮问一下这家公司吧,让我们都长点知识。呵呵,开个玩笑。
建议楼主看一看这家公司的配套源码,或者看清楚DS1302的Datasheet 从DS1302的时序上说,用SPI是可以的。
建议LZ检查一下3点;
1 把SPI的分频调到最大,因为1302的对数据的稳定时间要求是比较长的。
2 把1302到AVR的数据线弄的尽可能短些。
3 从1302读取数据的时候SPI的SPDR应该装入0XFF;
同问LZ这样接线有什么好处吗?
为什么不用模拟的时序?这样还省下一个IO. 回复【3楼】Jigsaw
-----------------------------------------------------------------------
原理图没问题之前做过 5楼可以把自己用过的SPI源码贴给楼主
从SPI的时序来说,这样读写是可以理解的。
之前是自己对SPI的细节没弄清楚,MISO时同样是下降沿采样,以为都是下降沿采样。
为自己的错误向楼主致歉! http://hi.baidu.com/282280072/blog/item/b5dd7da0d73ff88146106473.html
DS1302 SPI接口,proteus,虚拟终端显示
参考下吧好久了 多谢各位老师指导我现在改成用IO口模拟方式了,调试通过了,谢了 回复【8楼】panda1985 盼盼
-----------------------------------------------------------------------
我用GCCAVR作的SPI口可以对DS1302进行读和写操作,但好像是单工的。 ds1302 is spi, except that its slave select is active high, vs. active low for "standard" spi. MARK mark~~~~~~~~~~~~~~~ 和DS1302之间的通讯,我也正在头痛中
页:
[1]