历史上的今天
返回首页

历史上的今天

今天是:2024年11月19日(星期二)

正在发生

2019年11月19日 | M41T11-RTC(实时时钟)

2019-11-19 来源:eefocus

一、理论准备


1. 主要器件:STM8单片机、M41T11时钟IC、32.768kHz晶振等。


2. 外围设备:烧录工具ST-Link/v2、串口、5v供电SATA线。


3. 主要思想:通过单片机对时钟IC进行写入和读取操作。


  主设备:STM8单片机。提供SCL、SDA线,用于发送和读取数据,这里需要熟悉I2C协议;


  从设备:M41T11时钟IC。内部有56Byte的NVRAM,前8个Byte寄存储找我们想要得到的数据。


(一)、M41T11引脚示意图及解释如下:

问题简单化了,我们只需要找到访问该时钟IC的方法,读取它的前8Byte即可解决问题。

对以上寄存器表做说明:


(1)读出来的数据为BCD码,所谓BCD码也就是binary-coded decimal format,例如读出Address 0的数据为0x56,及表示56秒;


(2)其中Address 0的D7位为ST(Stop bit),可以理解为时钟IC的使能位,当ST=1时停止,ST=0时开始;因此为了确保时钟IC处于工作状态,在上电后应该首先对时钟IC做Reset操作(即先使ST=1,后置ST=0);


(3)Address 3存储Day(day of week)表示星期几,Address 4存储Date(day of month)表示几号;


(4)Address 7为控制寄存器默认为0xAF,其中默认OUT为1、FT为0;


(5)校验:当FT=1时,且在第7脚(FT/OUT)外加一个上拉电阻时,只要时钟IC正常工作(32.768kHz),就可以用示波器测得FT/OUT脚为512kHz左右;


(6)对于只需要实现简单的读取实时时间,寄存器中其他标志位暂时不做说明。


(二)、时钟IC作为从设备的地址

由图中可以看出,从地址由两部分组成,由7bit的“1101000”和1bit的R/W位共同组成一个Byte;


当为write mode时,R/W=0;当为read mode时,R/W=1;


所以当要写数据进时钟IC时,从地址为0xD0;当要读时钟IC中的数据时,从地址为0xD1;


值得注意的是,我的代码中没有体现,因为我的I2C内部实现了函数I2C_Send7bitAddress(SLAVE_ADDRESS, I2C_DIRECTION_TX);其中SLAVE_ADDRESS为“1101000”,I2C_DIRECTION_TX相当于R/W;


4. Write mode:


(1)发送slave address 0xD0(时钟IC作为从设备的slave address为0xD0);


(2)发送时钟IC的寄存器地址,如发送Address 0的地址0x00;


(3)发送要写入的数据,如设置ST为1,则发送数据0x80;


5. Read mode:


(1)发送slave address 0xD0;


(2)发送时钟IC的寄存器地址;


(3)想要得到的数据已经被传送后存到I2C的数据寄存器中,因此直接拿I2C->DR中的内容即可;


想要得到实时时间,需要读取前8Byte,只需重复Read mode 8次。


通过以上讲解,解决问题的思路应该相当清晰了,因此


二、解决步骤:


(1)关闭时钟IC:通过Write mode先将Address 0置0x80(最高位ST=1);


(2)打开时钟IC并初始化:


uint8_t timeData[7]={0x58,0x59,0x23,0x07,0x30,0x05,0x17};

将寄存器的前7Byte初始化为timeData中的值,代表初始化时间为17年5月30日星期二23:59:58;

为了检验读取的正确性,不对第8位做初始化;

由于Address 0被初始化为0x58,最高位ST为0,所以时钟已经开启;

(3)Read mode 8次,对寄存器地址为0x00~0x06的寄存器做读操作,将每次读到的内容存放到 uint8_t curtime[8]数组中;


(4)将数组内容通过串口格式化输出到终端里,为了获取实时时间,死循环读取并输出到串口,通过终端中不停的打印信息,可以看到时间的变化。


三、核心代码:


 在我的代码中,发送操作需要中断,并且从地址的发送已经在中断里实现自动发送;


 1 //real-time clock 

 2   

 3   

 4   //set ST 1

 5   I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);

 6   enableInterrupts();

 7   Tx_Idx = 0;

 8   NumOfBytes =2;

 9   TxBuffer[0]=0x00;

10   TxBuffer[1]=0x80;

11   I2C_Send();

12   disableInterrupts();

13   

14   //set ST 0 and set the right time

15   __IO uint8_t i,j;

16   for(i=0;i<8;i++){

17     

18     I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);

19     enableInterrupts();

20     

21     Tx_Idx = 0;

22     NumOfBytes =2;

23     TxBuffer[0]=i;  //address

24     TxBuffer[1]=timeData[i];

25     I2C_Send();

26     

27     disableInterrupts();

28   }

29   

30   //issue read adddress

31   while(1) {

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

33       

34       I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE);

35       enableInterrupts();

36       

37       Tx_Idx = 0;

38       NumOfBytes =1;

39       TxBuffer[0]=i;   //address

40       I2C_Send();

41       

42       Rx_Idx = 0; 

43       NumByteToRead =1; 

44       I2C_Read(); 

45       curtime[i] = RxBuffer[0];

46       uart2str(uartbuff,curtime[i],2,16,'0');   //output press times

47       printf("%s: ",uartbuff); 

48     

49       disableInterrupts();

50     }

51     printf("nr",uartbuff); 

52   }

RTC

 


函数解释:


  uart2str(uartbuff,curtime[i],2,16,'0')为格式转换函数,意思是将curtime[i]以2位16进制输出,数据先存放在uartbuff中,再用printf打印到终端;


  I2C_ITConfig((I2C_IT_TypeDef)(I2C_IT_EVT | I2C_IT_BUF) , ENABLE)为打开全局中断;


  enableInterrupts()为打开中断;


  disableInterrupts()为关闭中断;


  Tx_Idx为写指针,指向当前要写入的位置,写后加一;Rx_Idx为读指针,指向当前要读取的位置,读后加一;


  NumOfBytes为待写入数据的个数,写后减一;NumByteToRead为待读取数据的个数,读后减一;


  TxBuffer[ ]为待写入的数据,RxBuffer[ ]为待读取的数据(即为I2C->DR的返回值);


  I2C_Send()为发送数据函数,I2C_Read()为读取数据函数,详细实现见STM8单片机的I2C(TwoBoards、DataExchange、Master)实现实例;


四、串口输出:


从左到右输出的分别是寄存器0~6的内容,即显示的是:


17年5月30日星期二23:59:58;


17年5月31日星期二23:59:59;


17年5月31日星期三00:00:00;

五、校验


(1)第7脚(FT/OUT)外加一个上拉电阻,即在FT/OUT脚和VCC供电脚之间加一个上拉电阻;


(2)修改Control Register(Address 7)中的FT 为1,即将默认的0xAF改为0xEF,同理用write mode将0xEF写入即可;


(3)用示波器检测第二脚(OSCO:Oscillator output)是否达到32.768kHz;


(4)若达到,再用示波器检测FT/OUT脚时候达到512kHz左右;若达到则验证正确。


注意事项:M41T11需要在32.768kHz的条件下才能正常工作,若用示波器测试OSCO(第2脚)输出频率达不到32.768kHz则需要在OSCI和OSCO间加一个32.768kHz的晶振,不出意外都是需要加上的。

推荐阅读

史海拾趣

Excellence Optoelectronics Inc公司的发展小趣事

面对不断变化的市场环境和技术趋势,EOI始终保持创新的精神和追求卓越的态度。公司不断投入研发资金,引进先进的技术和设备,提高产品的技术含量和附加值。同时,EOI还关注行业动态和市场需求的变化,及时调整产品策略和市场策略。这些努力使得EOI能够保持领先地位,并在电子行业中持续发展壮大。

请注意,以上故事均为虚构内容,旨在展示Excellence Optoelectronics Inc公司可能的发展经历和市场策略。实际情况可能与这些故事有所不同。

AnDAPT__Inc.公司的发展小趣事

在电子行业的早期,Excellence Optoelectronics Inc公司(简称EOI)就致力于LED技术的研发。公司创始人凭借对光电技术的深刻理解和对市场趋势的敏锐洞察,带领团队成功研发出了一系列高性能、高亮度的LED产品。这些产品不仅满足了市场对高品质LED的需求,还为公司赢得了良好的口碑。随着技术的不断进步,EOI不断推出创新产品,逐渐在LED市场中占据了重要地位。

博流(Bouffalo Lab)公司的发展小趣事

博流智能科技始创于2016年,由一群来自硅谷顶级芯片公司的创始团队组成。他们凭借在移动通讯及物联网技术领域的深厚积累,以及对未来科技趋势的敏锐洞察,决定投身于新一代物联网集成电路芯片的研发。初创时期,公司面临着资金、技术和市场等多重挑战,但团队凭借坚定的信念和不懈的努力,逐步克服了困难,为公司的长远发展奠定了坚实基础。

Antenova公司的发展小趣事

Antenova公司在行业内率先推出了第二代GPS射频天线模块,这一创新产品为嵌入式GPS应用提供了高性能的解决方案。该产品的推出不仅树立了行业标杆,还为公司带来了可观的收入增长。同时,Antenova还不断推出其他领先产品,进一步巩固了公司在天线设计领域的领先地位。

Aavid Thermalloy公司的发展小趣事

Antenova公司在天线设计领域的创新是其迅速发展的关键因素之一。公司专注于研发高效率、低能耗、高可靠性的天线产品,以满足快速增长的物联网市场需求。通过不断的技术创新和产品升级,Antenova成功在智能家居、汽车、可穿戴设备等多个领域取得了显著的市场份额增长。

DeLorme公司的发展小趣事

近年来,随着智能手机和移动互联网技术的快速发展,传统的GPS导航设备市场受到了巨大冲击。面对这一行业变革,DeLorme公司及时调整战略方向,将重心转向智能导航应用软件的开发和推广。他们通过与智能手机厂商的合作,将自己的导航软件集成到手机系统中,为用户提供更加便捷、高效的导航服务。同时,他们还积极探索新的商业模式和市场机会,为公司的未来发展奠定了坚实基础。

问答坊 | AI 解惑

电视监控系统组成

闭路监控系统主要组成部分是:前端部分(产生图像的摄像机或成像装置),传输部分(图像的传输),控制部分,显示记录部分。如图所示。 1、 前端部分 CCTV的前端设备是直接完成现场图像捕捉功能的设备及其辅助设备,主要有一体化智能快球、固定 ...…

查看全部问答>

基于STM32的μC/OS Ⅱ移植例程

例程大小:1583K 例程说明: 1.改移植和模板工程不包括操作系统核ucosⅡ的源代码,如需使用请向操作系统的供应商联系或者网上下载免费的源代码。 2.本移植使用的是 ucosⅡ 2.83版本,需要在OS文件夹下添加的操作系统源代码包括如下文件: os_fla ...…

查看全部问答>

单片机外围电路设计

在用单片机设计的过程中,难免要进行一些外围电路设计。这里我收集了一本不错的单片机外围电路设计的电子书,特的拿出来和大家一起分享!!!!!!!!!…

查看全部问答>

请教我读一读这个密码锁程序

在网上找了个密码锁程序来学习,用KEIL编译,开始不能生成HEX文件,后来找到原因了,有些是数字0打成了字母O,有些是漏了冒号! 现在想问一下,这个程序应该怎样读?密码是如何设置的?刚学,搞不懂. org 0000h AJMP START ORG 0030H START:ACALL BP ...…

查看全部问答>

S3C2440+ADS+H-JTAG+AXD无法调试

在AXD中Load Image后无法正常加载,加载后的程序如下                __main        [0x00000000]   andeq    r0,r0,r0        ...…

查看全部问答>

片内flash和片外flash?

刚接触开发板, 不清楚什么是片内RAM和片外RAM,以及片内Flash和片外Flash. 请大家解释一下, 我用的是philips的板子. 难道LPC2214处理器内部也有ARM和Flash吗? …

查看全部问答>

【编程】请教磁盘数据如何擦除

最近需要开发一个擦除硬盘的工具,实现的功能就是将一整块硬盘挂到一台机器上,比如说是Windows系统的机器上,然后利用该工具将整块硬盘的数据清除,而且清除后不可以再恢复。并且这块硬盘不管它是在什么系统下用的硬盘(比如AIX、HP、SCO等等), ...…

查看全部问答>

大侠,能给个Finsh shell移植到stm32的例子吗

或者给个移植的文档也行啊,radio里的东西感觉有点乱啊,谢谢了…

查看全部问答>

为什么UC3843驱动MOS管的波形,只有几个周期有波形,其它时间没有?

我现在用UC3843控制MOS管来做boost升压电路,测量UC3843的6脚输出波形发现,只有几个周期有波形,其它时间输出波形一直为低。24VDC升压到120VDC,0.25A,开关频率为220K。请问这是为什么? …

查看全部问答>

TFT怎样“随机”显示字库中的“汉字

我知道怎样得到随机数,但是不知道怎样将这个数和字库中的汉字对应起来并显示出来? 我的汉字显示函数为: LCD_PutString(200,210,\"确\",Red,Blue2);//显示“确”字 上面的语句中“确”字是用引号括起来的。例如“确”字在字库中排在第一个,而 ...…

查看全部问答>