这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 【转载】STM32F1读写时钟芯片DS1307总结--from三叶

共1条 1/1 1 跳转至

【转载】STM32F1读写时钟芯片DS1307总结--from三叶

工程师
2024-02-20 23:57:58     打赏


这个帖子是个人学习STM32IIC通信的一个小总结,实现了STM32F103C8读写DS1307。

多年前买了原子哥的战舰开发板学习STM32,后来种种原因停滞了几年。前不久重新学习STM32,在空暇之余按照原子哥的不完全手册依次学习芯片各个自带资源,不过进度倒是比较慢了。

    学习IIC通信花了不少时间,这期间吃了亏,并再一次意识到看芯片手册的重要性。这里把操作DS1307的一些要点按自己的理解总结出来,希望需要的人少走弯路。


2 写DS1307

    图1截图自DS1307芯片手册。展示了主机写、DS1307接收模式时的数据流。一般是主机修改ds1307内储存的时间实现校时。步骤为:

1.        主机发送起始(start)信号

2.        主机发送DS1307器件地址(0XD0);

3.        主机等待DS1307响应ack

4.        主机发送要写入的DS1307内部寄存器的起始地址(秒的地址为0x00,星期的地址是0x04)

5.        主机等待DS1307响应ack

6.        主机依次发送DS1307内部寄存器的新数据

7.        主机等待DS1307响应ack

8.        主机发送停止(stop)信号


    上述过程中,

  • l如果主机只发送1个DS1307内部寄存器的新数据,之后就发送停止信号,那么就只修改了起始地址的数据。比如这个起始地址是0x01(分钟地址),新数据是0x32,那么分钟寄存器的值就更新为0x32。

  • l如果主机发送n个DS1307内部寄存器的新数据,那么就修改起始地址以及起始地址之后n-1个寄存器的数据,比如这个起始地址是0x02,新数据是{0x08,0x22,0x03},寄存器0x02、0x03、0x04的值都会被修改,即小时、日、星期寄存器的新值就分别是0x08、0x22、0x03


写一字节函数:

void Ds1307writeByte(u8 addr,u8 dat)

{

         u8 ack, i=0;

         IIC_soft_start();

         IIC_soft_write_byte(0xd0);

         IIC_wait_ack();

         IIC_soft_write_byte(addr);

         IIC_wait_ack();

         IIC_soft_write_byte(dat);

         IIC_wait_ack();

         IIC_soft_stop();

}


初始化DS1307函数,实际是就是多字节写入DS1307的函数

void InitDS1307(void)

{

         u8 i,ack;

         u8 InitTime[7] ={0x00,0x32,0x08,0x04,0x01,0x10,0x20};//2020-10-1 THU 08:32:00

         IIC_soft_start();

         IIC_soft_write_byte(0xd0);

         IIC_wait_ack();

         IIC_soft_write_byte(0x00);

         IIC_wait_ack();

         for(i=0;i<7;i++)

         {

                   Ds1307writeByte(i,InitTime);

                   IIC_wait_ack();

         }

         IIC_soft_stop();

}


3 读DS1307

    图2展示了主机读、DS1307发送模式时的数据流。一般是主机读取ds1307内储存的时间数据。步骤为:

1.        主机发送起始(start)信号

2.        主机发送DS1307器件地址(0XD0);

3.        主机等待DS1307响应ack

4.        主机发送要读取的DS1307内部寄存器的起始地址

5.        主机等待DS1307响应ack

6.        主机再次发送起始(start)信号(图中红圈部分)

7.        主机发送读命令(0XD1);

8.        主机等待DS1307响应ack

9.        主机依次接收n字节DS1307内部寄存器的数据(每接收1字节数据,就发送响应ack一次),读最后一个字节后发送响应nack一次表示通知DS1307不要再发送数据了;

10.    主机发送停止(stop)信号


    上述过程中,

  • l主机接收的字节数实际由主机自己决定,接收1个字节就发送停止信号,那么久相当于只读取了一个字节数据;接收6个字节就发送停止信号,那么就相当于读取了6个字节数据。

  • l假设发送的起始地址是0x01,接收了5个字节就发送停止信号,就相当于读取了寄存器0x01、0x02、0x03、0x04、0x05这5个寄存器的值



读一字节函数:

u8 DS1307_read_one_byte(u8 addr)

{

         u8 dat,ack;

         IIC_soft_start();

         IIC_soft_write_byte(0xd0);

         ack=IIC_wait_ack();

         IIC_soft_write_byte(addr);

         ack=IIC_wait_ack();

         IIC_soft_start();

         IIC_soft_write_byte(0xd1);

         ack=IIC_wait_ack();

         dat=IIC_soft_read_byte(1); //参数1—发送nack

         IIC_soft_stop();

         return dat;

}

读取多个字节

void DS1307_read_n_bytes(u8 addr_start,u8 byte_count,u8 *buf)

{

         u8 ack,i;

         IIC_soft_start();

         IIC_soft_write_byte(0xd0);

         ack=IIC_wait_ack();

         IIC_soft_write_byte(addr_start);

         ack=IIC_wait_ack();

         IIC_soft_start();

         IIC_soft_write_byte(0xd1);

         ack=IIC_wait_ack();

         for(i=0;i<byte_count-1;i++)

         {

                   *buf++=IIC_soft_read_byte(0);//参数0—发送ack

         }

         *buf =IIC_soft_read_byte(1);     //参数1—发送nack

         IIC_soft_stop();

}


4 总结

    实现IIC通信是最重要的一步,不过这里只说IIC应用,具体通信方式参考原子哥的不完全手册就行了。说句题外话,不完全手册是以读写AT24C02为例子进行说明的,要是读写AT24C32及更大容量的系列芯片,需要将地址分高低字节分别写入才能正确通信。

还有一点就是关于STM32引脚配置的问题,我本次使用PB4/PB5作为驱动IO,由于复位后PB4是作为JTAG的一个引脚,因此需要将PB4配置为普通IO口,参看复用重映射和调试I/O配置寄存器(AFIO_MAPR)的SWJ_CFG位,配置值的作用如图3所示。


    我使用的是一个最小系统,需要使用SW的下载功能,因此只关闭JTAG,配置代码如下:

         RCC->APB2ENR |=1<<0;//开启引脚复用时钟

         AFIO->MAPR |=2<<24; //010:禁止JTAG-DP,启用SW-DP;

来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。


共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]