mbed还没康复
莫非和google一样悲催啦
nucleo的RTC
昨天先是mbed站点坏掉
然后等了好几个小时,mbed终于康复了
然后EEPW服务器的网线又被老鼠咬断了
说一下nucleo的RTC吧
话说这个stm32L053R8处理器是带RTC的
(这里写着呢,https://developer.mbed.org/platforms/ST-Nucleo-L053R8/)
mbed也提供了一个显示时间的例子(尽管有点简陋):
#include "mbed.h" DigitalOut myled(LED1); int main() { printf("RTC example\n"); set_time(1387188323); // Set RTC time to 16 December 2013 10:05:23 UTC printf("Date and time are set.\n"); while(1) { time_t seconds = time(NULL); //printf("Time as seconds since January 1, 1970 = %d\n", seconds); printf("Time as a basic string = %s", ctime(&seconds)); //char buffer[32]; //strftime(buffer, 32, "%I:%M:%S %p\n", localtime(&seconds)); //printf("Time as a custom formatted string = %s", buffer); myled = !myled; wait(1); } }
其实核心就是这个set_time()
/** Set the current time * * Initialises and sets the time of the microcontroller Real-Time Clock (RTC) * to the time represented by the number of seconds since January 1, 1970 * (the UNIX timestamp). * * @param t Number of seconds since January 1, 1970 (the UNIX timestamp) * * Example: * @code * #include "mbed.h" * * int main() { * set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37 * } * @endcode */ void set_time(time_t t);
不过还好我们有
struct tm { int tm_sec; /* seconds after the minute, 0 to 60 (0 - 60 allows for the occasional leap second) */ int tm_min; /* minutes after the hour, 0 to 59 */ int tm_hour; /* hours since midnight, 0 to 23 */ int tm_mday; /* day of the month, 1 to 31 */ int tm_mon; /* months since January, 0 to 11 */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday, 0 to 6 */ int tm_yday; /* days since January 1, 0 to 365 */ int tm_isdst; /* Daylight Savings Time flag */ union { /* ABI-required extra fields, in a variety of types */ struct { int __extra_1, __extra_2; }; struct { long __extra_1_long, __extra_2_long; }; struct { char *__extra_1_cptr, *__extra_2_cptr; }; struct { void *__extra_1_vptr, *__extra_2_vptr; }; }; };
extern _ARMABI time_t mktime(struct tm * /*timeptr*/) __attribute__((__nonnull__(1))); /* * converts the broken-down time, expressed as local time, in the structure * pointed to by timeptr into a calendar time value with the same encoding * as that of the values returned by the time function. The original values * of the tm_wday and tm_yday components of the structure are ignored, and * the original values of the other components are not restricted to the * ranges indicated above. On successful completion, the values of the * tm_wday and tm_yday structure components are set appropriately, and the * other components are set to represent the specified calendar time, but * with their values forced to the ranges indicated above; the final value * of tm_mday is not set until tm_mon and tm_year are determined. * Returns: the specified calendar time encoded as a value of type time_t. * If the calendar time cannot be represented, the function returns * the value (time_t)-1. */
所以我们可以这样:
struct tm mytime; time_t seconds; mytime.tm_year = xxx; mytime.tm_mon = xxx; .... 然后: seconds = mktime(&mytime); set_time(seconds);
记得年是从1900年开始的,所以如果你需要存2015,那么赋值应该写成:
mytime.tm_year = 2015 - 1900;
同理月是从0开始的,所以,如果你想保存11月,那么赋值部分应该写:
mytime.tm_mon = 11-1;
这样是不是优雅多了?
nucleo的RTC续(一)
好吧,程序挺优雅的,自己先吐,免得被你们吐。
STM32L053R8带个RTC也挺优雅
mbed提供了rtc的读写也挺优雅
都优雅,那么貌似不用写什么续集了,骗字数也不能这样不厚道吧?
其实不然,别看楼主平时做事低调,但是做人是相当厚道的。
废话少说(其实是说了很多废话说不动了):
举个栗子,你买个手机,设置好时间后,关机再开机,时间又变成1900年1月1日,你啥心情
这个nucleo就系这样,新都睡了
设置完时间,不断电,按reset,时间就木有啦。
大神的改造,话说我完全看不懂他做的啥,画的啥。感兴趣的去看看
https://developer.mbed.org/users/kenjiArai/notebook/nucleo-series-rtc-control-under-power-onoff-and-re/
nucleo的RTC续(二)
如前所述,对于我等菜鸟,STM32L053R8的RTC想用起来是有极大的障碍啦。除非不断电也不重启。
还好,我手头有一个用于Arduino的ds3231模块,在Arduino上用着挺好的,就想想能不能用于这个上呢。
说做就做,先连上再说
5V, GND, SDA, SCL貌似这几根线需要连
按Arduino的连法(A4 SDA, A5 SCL)
I2C i2c(A4, A5);
然后上电RESET后给出提示:
(pinmap not found for peripheral)
研究半天,大概就是A4, A5没I2C功能 ,说好的兼容Arduino UNO R3呢
, 做人咋不信守承诺呢?
好吧,找一下针脚图
SDA, SCL对应的是D14, D15, 可以在程序中直接用:I2C_SDA, I2C_SCL代替
I2C i2c(I2C_SDA, I2C_SCL);
貌似不出错了
然后呢,试验一下能不能用吧
合计按Arduino的库改写一下,应该没啥难度吧
比如这个:
byte DS3231::getDate() { Wire.beginTransmission(CLOCK_ADDRESS); Wire.write(uint8_t(0x04)); Wire.endTransmission(); Wire.requestFrom(CLOCK_ADDRESS, 1); return bcdToDec(Wire.read()); }
看起来So Easy嘛
然后,仿照mbed I2C的例子改造一下
#include "mbed.h" // Read temperature from LM75BD I2C i2c(p28, p27); const int addr = 0x90; int main() { char cmd[2]; while (1) { cmd[0] = 0x01; cmd[1] = 0x00; i2c.write(addr, cmd, 2); wait(0.5); cmd[0] = 0x00; i2c.write(addr, cmd, 1); i2c.read(addr, cmd, 2); float tmp = (float((cmd[0]<<8)|cmd[1]) / 256.0); printf("Temp = %.2f\n", tmp); } }
#include "mbed.h" #define DS3231_ADDR (0x68) Serial pc(USBTX,USBRX); I2C i2c(I2C_SDA, I2C_SCL); DigitalOut myled(LED1); int main() { char data_write[10]; char data_read[10]; data_write[0] = 0x00; //data_write[1] = 0x02; int status ; status = i2c.write(DS3231_ADDR, data_write, 1, 0); pc.printf("Return Value:%d\r\n", status); if (status != 0) { //NO ACK pc.printf("I2C Write status Error\r\n"); } status = i2c.read(DS3231_ADDR, data_read, 7); pc.printf("\r\nReturn Value:%d\r\n", status); if (status != 0) { //NO ACK pc.printf("I2C Read status Error\r\n"); } for(int i=0; i<7; i++) pc.printf("%x\t", data_read[i]); pc.printf("\r\nI2C Test End!\r\n"); }
然后呢,貌似根本不工作
Return Value:1 I2C Read status Error ff ff ff ff ff ff ff I2C Test End! Return Value:1 I2C Write status Error
差哪里呢?
且看下文分解
nucleo的RTC续(三)
为啥例子里读那个LM75BD就会返回正确数据,而我这个就不能呢?
然后追踪了一下Arduino的代码。
在:
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)中
// build sla+w, slave device address + w bit twi_slarw = TW_READ; twi_slarw |= address << 1;
在:
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
// build sla+w, slave device address + w bit twi_slarw = TW_WRITE; twi_slarw |= address << 1;
在AVR C库手册中:
R/W bit in SLA+R/W address field. • #define TW_READ 1 • #define TW_WRITE 0
也就是说,地址其实是加上读写位后转换而来的地址。
另外,找了一下DS3231的文档:
果然如此、
nucleo的RTC续(四)
改写后的代码如下:
#include "mbed.h" #define DS3231_ADDR (0x68) #define TW_READ 1 #define TW_WRITE 0 Serial pc(USBTX,USBRX); I2C i2c(I2C_SDA, I2C_SCL); DigitalOut myled(LED1); int main() { char data_write[10]; char data_read[10]; data_write[0] = 0x00; //data_write[1] = 0x02; int status ; status = i2c.write( (TW_WRITE | DS3231_ADDR <<1) , data_write, 1, 0); pc.printf("Return Value:%d\r\n", status); if (status != 0) { //NO ACK pc.printf("I2C Write status Error\r\n"); } status = i2c.read( (TW_READ | DS3231_ADDR <<1), data_read, 7); pc.printf("\r\nReturn Value:%d\r\n", status); if (status != 0) { //NO ACK pc.printf("I2C Read status Error\r\n"); } for(int i=0; i<7; i++) pc.printf("%x\t", data_read[i]); pc.printf("\r\nI2C Test End!\r\n"); }
测试结果:
Return Value:0 Return Value:0 26 7 21 4 5 11 15 I2C Test End!
总算出数啦,累死我啦。
数据依次是:秒,分,小时,星期,日, 月,年
和当前时间完全一致啊,爽得不要不要的。
(数据是BCD编码存储的,我用16进制打印出来就是正确的,年,月和STM32L053R8的定义有些差异,需要注意)
有奖活动 | |
---|---|
发原创文章 【每月瓜分千元赏金 凭实力攒钱买好礼~】 | |
【EEPW在线】E起听工程师的声音! | |
“我踩过的那些坑”主题活动——第001期 | |
高校联络员开始招募啦!有惊喜!! | |
【工程师专属福利】每天30秒,积分轻松拿!EEPW宠粉打卡计划启动! | |
送您一块开发板,2025年“我要开发板活动”又开始了! | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏10分 | |
【我踩过的那些坑】DRC使用位置错误导致的问题被打赏100分 | |
我踩过的那些坑之混合OTL功放与落地音箱被打赏50分 | |
汽车电子中巡航控制系统的使用被打赏10分 | |
【我踩过的那些坑】工作那些年踩过的记忆深刻的坑被打赏100分 | |
分享汽车电子中巡航控制系统知识被打赏10分 | |
分享安全气囊系统的检修注意事项被打赏10分 | |
分享电子控制安全气囊计算机知识点被打赏10分 | |
【分享开发笔记,赚取电动螺丝刀】【OZONE】使用方法总结被打赏20分 | |
【分享开发笔记,赚取电动螺丝刀】【S32K314】芯片启动流程分析被打赏40分 |