STM32与DS1302通信问题
2019-03-23 19:02发布
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
本帖最后由 yangshihai1986 于 2013-12-26 19:25 编辑
各位前辈,大家好,我在写STM32与DS1302通信的时候遇到了一个问题
1,写1302时,写不进,读出的数据为0ff,源码如下
1302头文件:
#ifndef __DS1302_H__
#define __DS1302_H__
#include<stm32f10x_lib.h>
#include"delay.h"
#define ds1302_sec_add 0x80 //秒数据地址
#define ds1302_min_add 0x82 //分数据地址
#define ds1302_hr_add 0x84 //时数据地址
#define ds1302_date_add 0x86 //日数据地址
#define ds1302_month_add 0x88 //月数据地址
#define ds1302_day_add 0x8a //星期数据地址
#define ds1302_year_add 0x8c //年数据地址
#define ds1302_control_add 0x8e //写保护控制数据地址
#define ds1302_charger_add 0x90 //慢充电寄存器地址
#define ds1302_clkburst_add 0xbe //时钟突发模式寄存器地址
extern u8 time_buf1[8];//空年月日时分秒周
extern u8 time_buf[8] ;//空年月日时分秒周
void Ds1302_WriteByte(u8 ds1302_addr,u8 ds1302_data);//向DS1302写入一字节数据
u8 Ds1302_ReadByte(u8 ds1302_command);//从DS1302读出一字节数据
void Ds1302_WriteTime(void) ;//向DS1302写入时钟数据
void Ds1302_ReadTime(void) ;//从DS1302读出时钟数据
void Ds1302_init(void);//DS1302初始化
void Ds1302_display(void);//ds1302时间显示函数
#endif
1302.c文件:
#include<stm32f10x_lib.h>
#include "ds1302.h"
#include"delay.h"
u8 time_buf1[8] = {20,13,12,22,15,9,30,7};//空年月日时分秒周
u8 time_buf[8] ; //空年月日时分秒周
/************************************/
/********* DS1302初始化程序 *********/
void Ds1302_init(void)
{
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRH&=0xfffff0f0; //
GPIOA->CRH|=0x00000303; //端口A的第8脚和第10脚配置为通用推挽输出
GPIOA->ODR&=~(1<<8);//SCLK引脚置低
GPIOA->ODR&=~(1<<10);//RST引脚置低
Ds1302_WriteByte(ds1302_control_add,0x00); //关闭写保护
Ds1302_WriteByte(ds1302_sec_add,0x00); //振荡器工作允许
Ds1302_WriteByte(ds1302_control_add,0x80); //关闭写保护
}
/*************************************/
/***** 从DS1302中读取1个字节程序 *****/
u8 Ds1302_ReadByte(u8 ds1302_addr)
{
u8 i,read_data;
GPIOA->CRH&=0xffffff0f; //
GPIOA->CRH|=0x00000030; //端口A的第9脚设置为推挽输出
GPIOA->ODR|=1<<10;//RST引脚置高,启用ds1302数据总线
delay_us(5);
ds1302_addr|=0x01;//第0位:为1,表示读,为0表示写
delay_us(5);
for(i=0;i<8;i++)
{
if((ds1302_addr&0x01)==0)
GPIOA->ODR&=~(1<<9); //为0
else
GPIOA->ODR|=1<<9; //为1
GPIOA->ODR|=1<<8;//SCLK时钟信号置高
delay_us(5);
GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
delay_us(5);
ds1302_addr>>=1; //地址数据右移一位,为下一位读取做准备
}
GPIOA->CRH&=0xffffff0f; //
GPIOA->CRH|=0x00000080; //端口A的第9脚配置为上拉/下拉输入模式,此时可读取外部信号电平
for(i=0;i<8;i++)
{
read_data>>=1;//右移一位,准备接收一位数据
//read_data&=0x7f;
if((GPIOA->ODR&0x0200)==0x0200) //判断PA9口的电平是否为高
read_data|=0x80; //电平为高
else
read_data&=0x7f;//电平为低
GPIOA->ODR|=1<<8;//SCLK时钟信号置高
delay_us(5);
GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
delay_us(5);
}
GPIOA->ODR&=~(1<<10);//RST置为0,释放ds1302数据总线
delay_us(5);
return read_data; //返回采集到的数据
}
/*************************************/
/***** 向DS1302中写入1个字节程序 *****/
void Ds1302_WriteByte(u8 ds1302_addr,u8 ds1302_data)
{
u8 i;
GPIOA->ODR&=~(1<<10);//RST置为0
GPIOA->CRH&=0xffffff0f; //
GPIOA->CRH|=0x00000030; //端口A的第9脚配置为通用推挽输出
GPIOA->ODR|=1<<10;//RST置为1,启用ds1302数据总线
delay_us(5);
GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
delay_us(5);
ds1302_addr&=0xfe;//第0位:为1,表示读,为0表示写
delay_us(5);
for(i=0;i<8;i++)
{
GPIOA->ODR|=1<<8;//SCLK时钟信号置高
if((ds1302_addr&0x01)==0) //判断PA9口的数据是否为高
GPIOA->ODR&=~(1<<9);//为低电平
else
GPIOA->ODR|=1<<9; //为高电平
GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
delay_us(5);
ds1302_addr>>=1; //地址数据右移一位,为下一位读取做准备
}
for(i=0;i<8;i++)
{
if((ds1302_data&0x01)==0) //判断PA9口的数据是否为高
GPIOA->ODR&=~(1<<9); //为低电平
else
GPIOA->ODR|=1<<9; //为高电平
GPIOA->ODR|=1<<8;//SCLK时钟信号置高
delay_us(5);
GPIOA->ODR&=~(1<<8);//SCLK时钟信号置低
delay_us(5);
ds1302_data>>=1; //需写入的数据右移一位,为下一位写入做准备
}
GPIOA->ODR&=~(1<<10);//RST置0,释放ds1302数据总线
delay_us(5);
}
/************************************/
/****** 向DS1302中写入时间程序 ******/
void Ds1302_WriteTime(void)
{
u8 i,tmp;
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf1/10;
time_buf=time_buf1%10;
time_buf=time_buf+tmp*16;
}
Ds1302_WriteByte(ds1302_control_add,0x00); //关闭写保护
Ds1302_WriteByte(ds1302_sec_add,0x80); //暂停
Ds1302_WriteByte(ds1302_charger_add,0xa9); //涓流充电
Ds1302_WriteByte(ds1302_year_add,time_buf[1]); //年
Ds1302_WriteByte(ds1302_month_add,time_buf[2]); //月
Ds1302_WriteByte(ds1302_date_add,time_buf[3]); //日
Ds1302_WriteByte(ds1302_day_add,time_buf[7]); //周
Ds1302_WriteByte(ds1302_hr_add,time_buf[4]); //时
Ds1302_WriteByte(ds1302_min_add,time_buf[5]); //分
Ds1302_WriteByte(ds1302_sec_add,time_buf[6]); //秒
Ds1302_WriteByte(ds1302_day_add,time_buf1[7]); //周
Ds1302_WriteByte(ds1302_control_add,0x80); //打开写保护
}
/************************************/
/****** 从DS1302中读出时间程序 ******/
void Ds1302_ReadTime(void)
{
u8 i,tmp;
time_buf[1]=Ds1302_ReadByte(ds1302_year_add); //年
time_buf[2]=Ds1302_ReadByte(ds1302_month_add); //月
time_buf[3]=Ds1302_ReadByte(ds1302_date_add); //日
time_buf[4]=Ds1302_ReadByte(ds1302_hr_add); //时
time_buf[5]=Ds1302_ReadByte(ds1302_min_add); //分
time_buf[6]=(Ds1302_ReadByte(ds1302_sec_add)); //秒
time_buf[7]=Ds1302_ReadByte(ds1302_day_add); //周
for(i=0;i<8;i++)
{ //BCD处理
tmp=time_buf/16;
time_buf1=time_buf%16;
time_buf1=time_buf1+tmp*10;
}
}
主函数:
#include<stm32f10x_lib.h>
#include"led.h"
#include "sys.h"
#include "595.h"
#include "Timer.h"
#include "ds1302.h"
#include"delay.h"
// sc8 table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// sc8 table1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
u16 t2;
int main(void)
{
Stm32_Clock_Init(9);
led_init();
delay_init(72);
HC595_init();
Ds1302_init();
Timer2_Init(1000,7199);
delay_ms(200);
Ds1302_WriteTime(); //原始年月日数据读入
delay_ms(200);
while(1)
{
Ds1302_display();
// display(t2);
}
}
/********************************/
/***** 定时器2中断服务程序 *****/
void TIM2_IRQHandler(void)
{
if(TIM2->SR&0X0001)//溢出中断
{
t2++;
if(t2>=10)
{
t2=0;
Ds1302_ReadTime();
}
}
TIM2->SR&=~(1<<0);//清除中断标志位
}
请各位前辈多多指教
此帖出自
小平头技术问答
一周热门 更多>