完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
大家好,这些天我一直在用PIC18F27 K42工作,我已经“成功”了(因为我需要调试当前数据)与MPU6050模块进行通信,并生成MCC代码。现在我想在我的项目中添加一个RTC(DS1307)模块。问题是,我正在读取从设备的数据,数据在每一个循环期间都没有改变。我假设读秒的寄存器需要连续地变化,但是它没有。对于这两个接口,我都遵循这个网站:MPU6050:DS1307:我认为问题来自F。在等待ACK或NACK时,MCC似乎没有合适的设置,我认为MCC设置一个单一数据以从从属、ACK或NACK获得,而当数据不改变时,寻找NACK(我认为,根据DS1307数据表),问题是我不知道如何解决。我从MCC生成的I2C库代码中得到了这种数据持久性。我使用10K电阻作为PLUP。我使用的I2C2.C代码行:这些是我的RTC读取函数。变量是全局的,所以我只调用这个函数将当前数据设置为每个变量。当是显示值的时候,这是主代码,TFT函数是我的“控制台”来打印我从微控制器得到的。I2C2设置代码中可能有什么错误?也许我需要在阅读过程中从ACK切换到NACK?怎么办?我想答案来自I2C2CON1寄存器。期待听到一些提示,使这件事的工作!我没有显示MPU代码,因为它总是与当前的I2C配置正常工作。我测试了这两个,但问题是在DS1307模块(微型RTC模块)感谢您的时间。
以上来自于百度翻译 以下为原文 Hello guys, I've been working these days with the PIC18F27K42 and I've "successfully" (Since I need to debug current data) communicate with an MPU6050 module with the MCC code generated. Now I want to add an RTC (DS1307) module to my project. The problem is that I'm reading data from the slave device and data does not change at all during each while loop. I assume that the register that reads seconds needs to change continously but it doesn't. For both interfaces I followed this website: MPU6050: http://www.electronicwings.com/pic/mpu6050-gyroscope-accelerometer-temperature-interface-with-pic18f4550 DS1307: http://www.electronicwings.com/pic/real-time-clock-rtc-ds1307-interfacing-with-pic18f4550 I think that problem comes from the fact that MCC seems to not have a proper setup when is waiting for an ACK or a NACK, I think that MCC sets one single data to get from slave, an ACK or NACK, and that's when data doesn't change, looking for an NACK (I think, according to DS1307 datasheet) the problem is that I do not know how to solve this persistence of data from my I2C library code generated by MCC. I'm using 10k resistors as Pull-ups. My I2C2.c code lines used: void I2C2_Initialize(void) { if(!I2C2CON0bits.EN || lastError != I2C2_GOOD) { lastError = I2C2_GOOD; // TXU 0; CSD Clock Stretching enabled; ACKT 0; RXO 0; ACKDT Acknowledge; ACKSTAT ACK received; ACKCNT Not Acknowledge; I2C2CON1 = 0x80; // ABD enabled; GCEN disabled; ACNT disabled; SDAHT 300 ns hold time; BFRET 16 I2C Clock pulses; FME disabled; I2C2CON2 = 0x01; // CLK MFINTOSC; I2C2CLK = 0x03; // CSTR Enable clocking; S Cleared by hardware after Start; MODE 7-bit address; EN enabled; RSEN disabled; I2C2CON0 = 0x84; I2C2PIR = 0;// ;Clear all the error flags I2C2ERR = 0; } } uint8_t i2c2_read1ByteRegister(uint8_t address, uint8_t reg) { uint8_t result; I2C2_Initialize(); I2C2ADB1= (uint8_t)(address<<1); I2C2CNT=1; I2C2CON0bits.RSEN=1; I2C2CON0bits.S=1; //Start while (I2C2CON0bits.S); sendByte(reg); wait4MDRSetcount(1); address = (uint8_t)(address<<1); I2C2ADB1= (uint8_t)(address| 0x01); //Change the R/W bit for read I2C2CON0bits.S=1; //Start I2C2CON0bits.RSEN=0; result = receiveByte(); wait4Stop(); return result; } These are my RTC read functions. The variables are global, so I only call the function that this one will set current data to each variable. void RTC_Read_Clock(void) { sec = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x00); min = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x01); hour = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x02); } void RTC_Read_Calendar(void) { Day = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x03); Date = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x04); Month = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x05); Year = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x06); } When is time to show the values, this is the main code, TFT functions are my "console" to print what I got from the microcontroller. // main code uint8_t buf4[16]; uint8_t buf5[16]; uint8_t buf6[16]; while (TRUE) { Delay_ms(150); sprintf(buf4, "Sec = %X ", sec); TFT_Text(buf4, 20, 82, WHITE, BLACK); sprintf(buf5, "Min = %X ", min); TFT_Text(buf5, 20, 102, WHITE, BLACK); sprintf(buf6, "Hour = %X", hour); TFT_Text(buf6, 20, 122, WHITE, BLACK); } What could be wrong in the I2C2 setup code? Is it maybe that I need to switch from ACK to NACK during the readings? How could be done? I think that answer comes from the I2C2CON1 register. Looking forward to hear some hints to get this thing work! I'm not showing the MPU code, since it's always working normally with the current I2C configuration. I tested both but the problem is in the DS1307 module (TINY RTC module) Thank you for your time. |
|
相关推荐
16个回答
|
|
您没有显示定义,因为您写道,您可以通过I2C完全访问MPU9050,我不清楚您为什么这样想。当然,设备可能有不同的行为,但我不会开始用这个假设来寻找问题。你能检查一下你是否收到DS1307的ACK或NACK?你能和MPU9050的行为相比较吗?I2C时钟速度是多少?此外,我假设对于MPU9050(例如,每个通道有2个字节的3个通道)和DS1307,您按顺序读取多个字节(以相同的方式)。两个芯片使用相同的I2C总线?(I2C1BRead DealBooLoD可用于加速读出,但其他可选)
以上来自于百度翻译 以下为原文 You didn't show the definition of CLOCK_ADDRESS Since you wrote that you can perfectly access the MPU9050 via i2c, it's not clear to me why you think so. Of course the devices may behave differently, but I would not start searching for problems with that assumption. Did you / could you check whether you get an ACK or NACK from the DS1307 ? And could you compare with the behaviour of the MPU9050 ? What is the i2c clock speed ? Also I assume that for both MPU9050 (e.g. 3 channels with 2 bytes each) and DS1307 your read multiple bytes in sequence ( in the same way). Both chips use the same i2c bus ? (i2c1_readDataBlock might be used to speed up the read-out, but otherwise optional) |
|
|
|
不是一次读取一个字节,而是读取一个数据串。SMH。DS1307将自动推进寄存器指针。尝试读取I2C总线上的所有设备ID。它将列出IDS并返回一个计数,如果列表为NULL,否则将写入一个数组。
以上来自于百度翻译 以下为原文 Instead of reading a byte at a time, read a string of data. SMH. The DS1307 will auto-advance the register pointer. Try this to read all the device ids on the i2c bus. It will list the ids and return a count if List is null otherwise will write to an array. //---------------------------------------------------- #include #include #include "I2CLib2.h" section i2c_code,code; //---------------------------------------------------- int i2c_scan(unsigned char *List){ int cnt=0; for(int f=0;f<255;f+=2){ i2c_start(); while(I2CCON&0x1f); I2C1TRN=f; while(I2CSTATbits.TRSTAT); if(!I2CSTATbits.ACKSTAT){ cnt++; if(List)*List++=f; else printf("device 0x%02X foundr",f); } i2c_stop(); } return cnt; } //---------------------------------------------------- |
|
|
|
|
|
|
|
HM,实际上DS1307具有100千赫兹最大Fabian / MCC初始化,在手册中说I2C时钟选择寄存器值3意味着-gt;MFiToScC(500千赫),我看不到是否有任何附加除法器。MPU9050允许400 kHz,可能在一定限度内。对于DS1307。首先检查什么是有效的I2C时钟频率,如果它是500千赫选择另一个时钟源。
以上来自于百度翻译 以下为原文 Hm, indeed the DS1307 has 100 kHz max. Fabian / MCC initializes // CLK MFINTOSC; I2C2CLK = 0x03; where the manual says that the I2C clock selection register value 3 means -> MFINTOSC (500 kHz) I cannot see whether there is any additional divider. The MPU9050 allows 400 kHz, which might be within some limits. 500 kHz will be too high for the DS1307. First check what is the effective i2c clock frequency and if it is 500 kHz choose another clock source. |
|
|
|
输入时钟除以4或5(取决于另一位设置),所以I2C时钟将是125或100kHz。
以上来自于百度翻译 以下为原文 The input clock is divided by either 4 or 5 (depending on another bit setting) so i2c clock will be 125 or 100KHz |
|
|
|
好,看看FME位,我也看到500千赫总是被分割。FME位为0,这意味着FSCL=FCLK/5=100 kHz。时钟没有问题…
以上来自于百度翻译 以下为原文 OK, looking at the FME bit, I also see that the 500 kHz is always divided. The FME bit is 0 here // CSTR Enable clocking; S Cleared by hardware after Start; MODE 7-bit address; EN enabled; RSEN disabled; I2C2CON0 = 0x84;and this means FSCL = FCLK/5 = 100 kHz. No problem with the clock ... |
|
|
|
您好,谢谢您的答复。时钟从地址是0x68。确实,我设置了I2C模块工作在100kHz,因为我看到DS1307工作在100kHz,所以为了避免任何问题,我检查了频率是在设置与I2C应用笔记TB3191。所以所有的设备都在相同的频率下工作,并且使用相同的功能。通过终端,看起来I2C2读函数总是读取并给我这些值。这行代码必须读取秒数,输出总是0xFF:
以上来自于百度翻译 以下为原文 Hello and thanks for your replies. The clock slave address is 0x68. Indeed, I set the I2C Module to work at 100KHz as I saw that DS1307 works at 100KHz, so to avoid any issues from there I checked that frequency was on that setup with the I2C application note TB3191. So all devices works at same frequency and working with the same functions. The prints function gives the message "done!" through the terminal, so it looks like the i2c2 read function is always reading and giving me these value. This line of code has to read the seconds elapsed, the output is always 0xFF: sec = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x00); sprintf(buf, "seconds = %X ", sec); TFT_Text(buf, 20, 82, WHITE, BLACK); prints("done!nn"); |
|
|
|
你不应该仅仅依靠回报价值。如果考虑到超时,则接收字节函数可以返回没有有效值的函数。你可以用I2C2Y-GETLASTOrror检查,虽然返回的值应该是0,而不是0xFF。I2C地址0x68应该是可以的。您可以通过发出错误的I2C地址(例如0x70)来检查代码的行为,看看会发生什么。如果结果是相同的,那么您可能没有从DS1307读取这些0xFF值。
以上来自于百度翻译 以下为原文 You should not just rely on the return value. E.g. receiveByte function can return without valid value, if it considers a time-out. You can check with i2c2_getLastError, though the returned values then should be 0 instead of 0xff. i2c Address 0x68 should be ok. You could easily check the behaviour of your code by issuing a wrong i2c address, e.g. 0x70 and see what happens. If the result is the same, then you likely did not read these 0xff values from the DS1307. static inline uint8_t receiveByte(void) { uint8_t delayCounter = 255; if(lastError == I2C2_GOOD) { while(--delayCounter) { if(I2C2STAT1bits.RXBF) { return I2C2RXB; } else { __delay_us(1); } } lastError = I2C2_FAIL_TIMEOUT; } return 0; } |
|
|
|
我尝试您的建议RodiMs,我遵循这里的一段代码:用这个代码检查错误状态:我尝试用0x68、0x69和0x70.0x68:这对应于DS1307从数据表的从地址,所有我得到的是0xFF。这从一开始就是同样的行为。也许我需要在DS1307寄存器中设置其他位来启动时钟?0x69:这是MPU6050从地址,它给出了另一个值:103,一个没有在寄存器映射中注册,但是由于从设备工作正常,我不担心。0x70:这是一个随机地址来查看输出,我得到的是消息:“DS1307超时”。看来,我正在读DS1307,但时钟没有运行。我将用ARDUIO测试模块,看看是否会损坏模块,一切皆有可能。
以上来自于百度翻译 以下为原文 I try your suggestion rodims, I follow a piece of code from here: http://www.microchip.com/forums/m1049951.aspx with this code to check the error states: fanSensor = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x00); //Get value of seconds error=i2c2_getLastError(); // Check if any error occur if(error==I2C2_FAIL_TIMEOUT) { //display error occur TFT_Text("DS1307 TIMEOUT ", 10, 40, WHITE, BLACK); } else { //no error, display the sensor value sprintf(buf, " %02d", fanSensor); TFT_Text(buf, 10, 80, WHITE, BLACK); } I try with 0x68, 0x69 and 0x70. 0x68: This corresponds to the DS1307 slave address according to datasheet, all I got is 0xFF. Which is the same behaviour from the beginning. Maybe I need to set other bit in the ds1307 registers to start the clock? 0x69: This is the MPU6050 slave address, which gives another value: 103, that one is not registered in the register map, but since this slave devices is working correctly, I don't worry about that. 0x70: This is a random address to see the output, what I got was the message: "DS1307 TIMEOUT". So, looks like I am reading the DS1307, but the clock is not running. I will test the module with an Arduino to see if I may damage the module, everything could be possible. |
|
|
|
我解决了这个问题,问题是电源问题。出于某种原因,我只能用我拥有的一个ARDUINO UNO板来工作。所以,使用这个板,寄存器的读数改变了,现在我想解码来自DS1307的数据。我已经跟随YouTube视频了:它只发送来自时钟记录器寄存器的每个字节的读取请求。但是当我打印这些值时,我得到了一些非常奇怪的输出:IME:1?& lt;& gt;7?…19:;=:?……日期:7?-?- 00…= 7?-00我认为我的问题可能是tftx文本函数,将数据转换为ASCII等效值。有什么想法吗?
以上来自于百度翻译 以下为原文 I fixed the issue. The problem was in the power supply. For some reason, I can only make it work with one Arduino UNO board that I have. So, using this board the readings to the register changes and I now want to the decode the data that comes from the DS1307. I've follow a youtube video for this: https://www.youtube.com/watch?v=1Pguv4Ha7jY&t=1s It's only sending reading requests, for each byte from the timekeeper register. // global variables for time int second, minute, hour, hr, day, dday, month, year; char time_[] = "00:00:00"; char date_[] = "00-00-00"; unsigned char MSB(unsigned char x) { return ((x >> 4) + '0'); } unsigned char LSB(unsigned char x) { return ((x & 0x0F) + '0'); } // main function TFT_ConstText("Time:", 10, 40, WHITE, BLACK); TFT_ConstText("Date:", 10, 60, WHITE, BLACK); while (TRUE) { Delay_ms(1000); second = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x00); minute = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x01); hour = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x02); hr = hour & 0b00011111; dday = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x03); day = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x04); month = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x05); year = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x06); time_[0] = MSB(hr); time_[1] = LSB(hr); time_[3] = MSB(minute); time_[4] = LSB(minute); time_[6] = MSB(second); time_[7] = LSB(second); date_[0] = MSB(day); date_[1] = LSB(day); date_[3] = MSB(month); date_[4] = LSB(month); date_[6] = MSB(year); date_[7] = LSB(year); TFT_Text(time_, 70, 40, WHITE, BLACK); TFT_Text(date_, 70, 60, WHITE, BLACK); } But when I print the values, I got some very weird outputs: Time: 1?:<>:7? ...19:;=:?>.... and so on Date: 7?-;?-00... >=-7?-00 I think that my problem could be the TFT_Text function, converting data to ASCII equivalent values. Any ideas? |
|
|
|
易于测试。替换:看是否得到预期的输出。
以上来自于百度翻译 以下为原文 Easy to test. Replace: second = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x00); minute = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x01); hour = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x02); hr = hour & 0b00011111; dday = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x03); day = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x04); month = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x05); year = i2c2_read1ByteRegister(CLOCK_ADDRESS, 0x06); with second = 0x56; minute = 0x34; hour = 0x12; day = 0x16; month = 0x05; year = 0x18; and see if you get the expected output. |
|
|
|
[7:] 7位地址为68,位(0)为RD/WR,使其为D1用于读和D0写入。从RTC读取BCD值,然后打印在H.Pr.Trf或LCDApRITCF(“%02x:%02X.%02xr”),时间[0 ],时间[1 ],时间[4]);
以上来自于百度翻译 以下为原文 The [7:1] 7bit address is 68, bit [0] is rd/wr, making it D1 for reading and D0 for writing. Read the bcd values from the rtc, print then out in hex. printf or lcd_printf("%02x:%02x.%02xr", time[0], time[1], time[2]); |
|
|
|
还有一个警告。当我给DS1307加电时,前8个字节经常读为80、00、00、01、01、01、00、03,这与寄存器0的手动位7一致的是时钟停止(CH)位。当该位设置为1时,振荡器被禁用。当清零至0时,振荡器被启用。在第一次向设备施加功率时,时间和日期寄存器通常被重置为01 / 01 / 00 01 00∶00(MM/DD/YY DOW HH:MM:SS)。秒寄存器中的CH位将被设置为1IF,将CH位设置为0,时钟开始运行。所以我假设您有一个附加的电池,而CH位仍然是由ARDUINO的一些早期实验所设置的。正如QHB和Gort所暗示的:你是否考虑了读V?ALUE是BCD值,您需要屏蔽一些控制位,如CH和PM/AM?
以上来自于百度翻译 以下为原文 One more caveat. When I power up the DS1307 the first 8 bytes read constantly as 80 00 00 01 01 01 00 03 This is in accordance to the manual Bit 7 of Register 0 is the clock halt (CH) bit. When this bit is set to 1, the oscillator is disabled. When cleared to 0, the oscillator is enabled. On first application of power to the device the time and date registers are typically reset to 01/01/00 01 00:00:00 (MM/DD/YY DOW HH:MM:SS). The CH bit in the seconds register will be set to a 1 If I set the CH bit to 0, the clock starts to run. So I assume you have a battery attached, and the CH bit still was set by some earlier experiment with the Arduino. As implicitly mentioned by qhb and Gort: Did you take into account that the read values are BCD values and that you need to mask off some control bits like CH and PM/AM ? |
|
|
|
如果RTC正在运行,则不需要屏蔽CH,因为它将是零。AM/PM 12 /24小时需要被屏蔽。该函数返回32位长值。[23:0]=24位HH:mm。SS(24)=AM/PM,如果12HR时钟。[2]=12HR时钟,如果设置24HR。
以上来自于百度翻译 以下为原文 If the rtc is running, you don't need to mask out CH since it will be zero. AM/PM 12/24HR needs to be masked out. This function returns a 32bit long value. [23:0] = 24bit HH:MM.SS [24] = AM/PM if 12HR clock. [25] = 12HR clock if set else 24HR .include "DS3231RTCLib2.inc" .globl _rtc_gettime .section DS3231RTC,code ;---------------------------------------------------- .equ time_L, w6 .equ time_H, w7 ;rtn time, w1:w0 ;[23:0] HHMMSS, [24]=AM/PM, [25] = 24/12HR _rtc_gettime: ;long rtc_gettime(); mov #I2C_DS3231_RTC,w0 mov #RTC_SECONDS,w1 mov #WREG6,w2 mov #3,w3 call _i2c_gets ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;12hr or 24hr? btss time_H,#6 bra clock24hr ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;12hr clock mov.d time_L,w0 and #0b11111,w1 btsc time_H,#5 ;am/pm? bset w1,#8 ;pm bset w1,#9 ;12hr clock return ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ clock24hr: and #0b111111,time_H mov.d time_L,w0 return ;---------------------------------------------------- .end |
|
|
|
嗯?TFTXTY()的其他用法告诉我们它正在期待ASCII。您的DATEY和TIMEL数组值是二进制的。我想你需要转换为ASCII,而不是TftjTeXTo()。提示:二进制值0到9可以简单地通过添加“0”来浪费他们的带宽来转换成相应的ASCII字符。我错过了MSB()和LSB()进行转换的要点。问候,戴夫
以上来自于百度翻译 以下为原文 Huh? Sorry for wasted bandwidth. I missed the point that MSB() and LSB() do the conversion. Regards, Dave |
|
|
|
不,它们是.LSB()和MSB.()函数调用正在进行ASCII转换。
以上来自于百度翻译 以下为原文 No they aren't. The LSB() and MSB() function calls are doing the ASCII conversion. |
|
|
|
只有小组成员才能发言,加入小组>>
5170 浏览 9 评论
2001 浏览 8 评论
1931 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3176 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2228 浏览 5 评论
737浏览 1评论
622浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
509浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
635浏览 0评论
531浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 20:13 , Processed in 1.744083 second(s), Total 108, Slave 91 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号