关于STM32驱动DS1302的一点思考

本文讲述了作者在使用STM32驱动DS1302时遇到的问题及解决方法,包括DS1302的3线SPI读写方式、STM32的IO配置、位带操作的限制以及读写时序的重要性。通过解决电压、时序、IO配置等问题,实现了DS1302的精确读取时间。
摘要由CSDN通过智能技术生成

之前用51驱动过DS1302,没用多久就输出了正确的时间。当时以为这块芯片其实没啥,很简单。但是现在用STM32做项目,用到同样的芯片,以为这有何难,只要把那个程序拿过来复制黏贴改一下IO设置不就行了?但是事情远没有想想的那么简单。               

经过3天的挣扎,现在才知道当时自己是多么天真。

关于DS1302的基本操作可以看这里:http://www.cnblogs.com/qsyll0916/p/7712695.html

好了,废话少说了,进入正题。

首先DS1302读写方式属于3线SPI。CE、SCK、IO。其中IO口属于双向IO口,我们读写都要经过这个IO口。在用51开发的时候,因外他是准双向IO,不需要我们额外关心他的输入输出设置。需要输出的时候直接写            P0^1 = 1;   

需要检测外部输入的时候直接写       if(P0^1 == 1)   ,

都很方便,但是方便的同时带来的是读写速度上的限制。那么在STM32中,每个IO口都有8种输出模式。复杂的同时也意味着每一种模式都是专门定制的,带来了速度上的优势。所以在移植这个程序的时候,就需要注意这个双向IO的设置问题。一开始我也不是很懂,各种百度查资料,各种问人。最后才知道有两种方式可以实现双向的IO读写设置。

第一:

#define DS1302_DATIN        PBin(6)  
#define DS1302_DATOUT       PBout(6)

#define DS1302_DAT_INPUT()     {GPIOB->CRL&= 0XF0FFFFFF;GPIOB->CRL|= 8<<24;}  //设置成上拉或者下拉输入模式,需要外接上拉电阻
#define DS1302_DAT_OUTPUT()    {GPIOB->CRL&= 0XF0FFFFFF;GPIOB->CRL|= 3<<24;}  //设置成最大50M的通用推挽输出

通过简单的寄存器操作,可以实现输入输出的快速切换。需要在端口处接上拉电阻。

第二:

复制代码
    GPIO_InitTypeDef GPIO_InitStruct;  
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  

    GPIO_InitStruct.GPIO_Pin = DS1302_IO_PIN;         //这里最好设成开漏,当然也可以普通推挽,但是需要后面一直切换输入输出模式
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;     //开漏输出,需要接上拉,不需要切换输入输出了。
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    //输出速度50MHz  
    GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
复制代码

把IO配置成开漏输出模式。必须外接上拉电阻,不然读出的全是低电平。这样就不用一直切换输入输出模式,可以直接像51那样,直接使用。

双向IO的配置基本上就是上面所说的两种情况,但是可能还有其他方式,但是我目前就只知道这个方式,后面学习了在补充。

配置完IO之后就开始对IO进行操作,从而读写DS1302,获取实时时间。读写的时候特别需要注意。网上很多教程都没有提到这一点,估计是太基础了吧。但是这个小小的问题却困扰了我很长时间。就是在进行对DS1302的写命令和数据的操作的时候,我们需要按照从低位到高位依次发送数据。发送数据的时候:

在51里面我们经常会这样写:{    SCIO = byte_1 & 0x01;  byte_1 >> = 1;    }

那么在32中我们可以这样写吗?:   {    PBout(6) =  byte_1 & 0x01;  byte_1 >> = 1;    }

绝对不行。虽然看上去没有什么问题,也不会报错,但是却就是不同正确通信。很气人。

原因是PBout(6)这样的操作是属于STM32的位带操作。但是在CM3中不允许位带操作赋值除0和1以外的数。

也就是说上面那种操作方式是给  PBout(6) 赋值2,3,4,之类的数,但是stm32却不能理解这是什么意思。因为它只认识0和1!!!

所以我们可以简单的这样处理:

复制代码
        if((byte_1 & t) != 0)     //之前的问题出在这里,32的位带操作不能赋值0和1之外的值。
        {
            DS1302_DATOUT = 1;
        }
        else
        {
            DS1302_DATOUT = 0;
        }
复制代码

这样就可以正常通信了。但是如果不能像上面那样处理的话,现象是一直读出85这个数。关于读出85这个数,除了上面我提到的这种特殊情况,网上还是有很多人有这方面的经验的,我总结了一下,大致是下面这几种情况:

1、读取完时间后没有把DATA_IO引脚拉低。导致显示问号和85等一些乱七八糟的东西。但是我加了。
2、电压不够,小于4.6V。但是这个网上有争议,我接的是5V,实测4.8V,应该没问题。
3、没有接上拉电阻。我只在需要双向IO的地方加了上拉电阻,利用的是板子上预留的IIC的SDA,上面有一个4.7K的上拉,我把IO接在了这里。应该也没问题
4、仿真时序不对。但是我之前用这个时序在51上面实现过

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值