搜索
打印

[PIC®/AVR® MCU] 【CuriosityNano测评报告】04.I2C通讯实验及驱动DS1307日历模块

[复制链接]
45956|5
跳转到指定楼层
楼主
hu9jj|  楼主 | 2021-6-3 15:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#申请原创#
    之前多次测试PIC及AVR的核心板都是使用模拟I2C来对DS1307日历模块进行读写操作,感觉硬件I2C操控起来不知从何处下手,没有模拟I2C那么得心应手。为了熟悉和掌握硬件I2C的使用,本次就没有使用模拟I2C,直接进行硬件I2C的测试。
    在用MCC进行配置的时候,可以添加一个I2C使用的范例文件:


    在这个范例文件中为我们提供了几个I2C读写操作的函数:


    在以前的评测中我也曾经尝试过使用硬件I2C,但从来设有成功过。经过多次测试和分析,后来明白了在使用这些函数时,I2C器件的地址要用7位而不是我习惯的8位,因为在读写操作时,函数会将7位地址左移1位然后再加上读写操作码。
    关于DS1307日历模块网上有很多的资料,这里只是简单介绍一下数据的储存方式和读写操作:


    开机时一般先读入地址0的数据,若CH(位7)为1,则表明日历模块尚未启动,应该对其设置日期及时间,因此我们要用上读指定地址一个字节数据的函数;
    设置日期及时间需要连续写入7~8个字节的数据,因此我们需要使用写多个字节数据的函数;
    同样,在读取日历模块的日期及时间需要使用读多个字节的函数:
    在测试过程中,读取一个字节数据的函数没有问题,一次调试即成功:
  1. /******************************************************************************************
  2. * 函数名称:        DS1307_Init()
  3. * 功能说明: 用当前日期(yesr,month,day,hour,minute,second)初始化DS1307
  4. * 输    入: 无
  5. * 输    出: 无
  6. ******************************************************************************************/
  7. void DS1307_Init(void)
  8. {
  9.     uint8_t i;
  10.    
  11.     i = I2C1_Read1ByteRegister(DS1307_Addr_7,0);
  12.    
  13. //    LCD_write_value(0,3,3,0,0,i);//监测读取值
  14.     if(i > 127){
  15.         year = 2021;
  16.         month = 5;
  17.         day = 31;
  18.         week = 1;
  19.         hour = 14;
  20.         minute = 30;
  21.         second = 0;
  22.         DS1307_write_date();
  23. //         I2C1_WriteNBytes(DS1307_Addr_7,DS_Buff,8);
  24.     }
  25.     else
  26.         DS1307_read_date();
  27. }
复制代码


    开始测试时,初始化日期写操作使用的是I2C1_WriterNBytes()函数(也就是上面代码中注释行),但读取时日期数据不正确,通过使用逻辑分析仪抓取时序,发现基本操作是符合要求的,但实际写入的数据却大相径庭,完全不是数组中的值:


    我将要写入的数据与实际写入的数据进行了对比,两者之间没有规律,不知道是什么原因造成的,也许是数据传递过程中出了问题吧:


    之后我测试了单个数据的写入函数,写入正确,于是是只好通过循环,依次将数组中的数据写入,下面是最后通过的写操作函数:
  1. /******************************************************************************************
  2. * 函数名称:        DS1307_write_date()
  3. * 功能说明: 读取DS1307日期时间数据
  4. * 输    入: 无
  5. * 输    出: 无
  6. ******************************************************************************************/
  7. void DS1307_write_date(void)
  8. {
  9.     uint8_t i;
  10.     DS_Buff[0] = 0;                                             //秒
  11.     DS_Buff[1] = ((minute/10)<<4|(minute%10)); //分
  12.     DS_Buff[2] = ((hour/10)<<4|(hour%10));       //时
  13.     DS_Buff[3] = week;                                       //星期
  14.     DS_Buff[4] = ((day/10)<<4|(day%10));          //日
  15.     DS_Buff[5] = ((month/10)<<4|(month%10));   //月
  16.     DS_Buff[6] = ((year%100)/10<<4|(year%10)); //年
  17.     DS_Buff[7] = 16;                                          //0001 0000 = 允许按1Hz输出方波,低电平触发

  18.     for(i=0; i<8; i++ ){
  19.         I2C1_Write1ByteRegister(DS1307_Addr_7,i,DS_Buff[i]);  //写入8个字节数据
  20.     }
  21. }
复制代码


    读操作的函数测试很顺利,没有什么时周折:
  1. /******************************************************************************************
  2. * 函数名称:        DS1307_read_date()
  3. * 功能说明: 读取DS1307日期时间数据
  4. * 输    入: 无
  5. * 输    出: 无
  6. ******************************************************************************************/
  7. void DS1307_read_date(void)
  8. {
  9.     I2C1_ReadDataBlock(DS1307_Addr_7,0,DS_Buff,7);         //读取前7个字节数据
  10.    
  11.     second = ((DS_Buff[0]&0x70)>>4)*10 + (DS_Buff[0]&0x0F);//秒,屏蔽秒的第7位的标志
  12.     minute = ((DS_Buff[1]&0x70)>>4)*10 + (DS_Buff[1]&0x0F);//分(取低7位)
  13.     hour = ((DS_Buff[2]&0x30)>>4)*10 + (DS_Buff[2]&0x0F);  //时(取低6位)
  14.     week = (DS_Buff[3]&0x07);                              //周(取低3位)
  15.     day = ((DS_Buff[4]&0x30)>>4)*10 + (DS_Buff[4]&0x0F);   //日(取低6位)
  16.     month = ((DS_Buff[5]&0x10)>>4)*10 + (DS_Buff[5]&0x0F); //月(取低5位)
  17.     year = 2000 + (DS_Buff[6]>>4)*10 + (DS_Buff[6]&0x0F);  //年
  18.    
  19. }
复制代码


    这是测试过程的照片:


    这是LCD日历显示的效果:


    这是测试项目的压缩包:
MyTest.X.rar (1.23 MB, 下载次数: 6)

使用特权

评论回复
沙发
pzsh| | 2021-6-3 20:16 | 只看该作者
本帖最后由 pzsh 于 2021-6-3 20:45 编辑

这个是使用的Q40上的I2C外设直接实现的?

使用特权

评论回复
板凳
hu9jj|  楼主 | 2021-6-3 21:12 | 只看该作者
pzsh 发表于 2021-6-3 20:16
这个是使用的Q40上的I2C外设直接实现的?

是的,使用硬件I2C进行读写DS1307.

使用特权

评论回复
地板
weifeng90| | 2021-6-3 21:26 | 只看该作者
模拟效率不高

使用特权

评论回复
5
hu9jj|  楼主 | 2021-6-4 08:59 | 只看该作者

    不一定吧?模拟I2C只要仔细调整延时,让时序在标准范围内,可以达到同样的效率,只不过调整起来比较费时间。

使用特权

评论回复
6
yangjiaxu| | 2021-6-4 14:56 | 只看该作者
真挺好 讲的很详细

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

本版热帖

本版活跃用户

优质原创写原创,赢大奖

编辑推荐

  • 1 kk的回忆 得到打赏 ¥600.00
  • 2 名字还没想好 得到打赏 ¥350.00
  • 3 天意无罪 得到打赏 ¥312.00
  • 4 wolfe_yu 得到打赏 ¥210.00
  • 5 呐咯密密 得到打赏 ¥170.00
  • 6 gaoyang9992006 得到打赏 ¥120.00
  • 7 CZF11 得到打赏 ¥100.00
  • 8 年轻的国王 得到打赏 ¥90.00
  • 9 hunteredward 得到打赏 ¥90.00
  • 10 blust5 得到打赏 ¥85.00
在线客服 快速回复 返回顶部 返回列表