完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我用32.768 kHz的DS1307芯片编写了PIC16F87A中的RTC程序。它在proteus中运行正常,但硬件故障。谁能给我解决的办法…我在MPLAB IDEG866中编写了HealTeCC-C代码,调试器是PIC-KIT3。正常的LCD程序工作正常,但RTC程序不工作。我在这里附上我写的代码。
以上来自于百度翻译 以下为原文 I wrote a program for RTC in PIC16F877A using DS1307 IC with 32.768KHZ. Its working properly in Proteus but it failed in Hardware.. Anyone give me the solution.. I am writing HighTech-C code in MPLab IDEV8.66 and the debugger is Pic-Kit3. Normal LCD program works properly but RTC program is not working. I here to attach the code which i written.. #include #define _XTAL_FREQ 20000000 __CONFIG(0x3F3A); #define lcd PORTD #define rs RE0 #define rw RE1 #define en RE2 int i[7],dd; void delay(unsigned int a) { while(a--); } void pulse() { en=1; delay(100); en=0; delay(100); } void type() { rs=0; rw=0; lcd=0x38; pulse(); } void on() { rs=0; rw=0; lcd=0x0E; pulse(); } void address(int a1) { rs=0; rw=0; lcd=a1; pulse(); } void display(char d) { rs=1; rw=0; lcd=d; //delay(200); pulse(); } void string(char *c) { while(*c) { rs=1; rw=0; lcd=*c; *c++; pulse(); } } void wait() { while(SSPIF==0); SSPIF=0; } void start() { SEN=1; //start condition enable bit wait(); } void stop() { PEN=1; // stop condition enable bit wait(); } unsigned char send(unsigned char send) { ACKSTAT=1; //acknowledge not received from slave SSPBUF=send; while(ACKSTAT==1); //will be 0 if ack received from slave wait(); } void check() { //if((i[2]&0b00100000)==0) if(dd==1) { string(" AM"); } else { string("PM"); } } void checkday(int a4) { if(a4==1) { string(" Sun"); } else if(a4==2) { string(" Mon"); } else if(a4==3) { string(" Tue"); } else if (a4==4) { string(" Wed"); } else if(a4==5) { string(" Thu"); } else if(a4==6) { string(" Fri"); } else if (a4==7) { string(" Sat"); } } void restart() { RSEN=1; //repeated start condition enable bit wait(); } void conv(unsigned char i[]) { address(0xc0); display(((i[4]& 0x30) >>4) + 0x30); display((i[4]& 0x0f) + 0x30); display('-'); display(((i[5] & 0x10) >>4) + 0x30); display((i[5] & 0x0f) +0x30); display('-'); display(((i[6]& 0xf0) >>4) + 0x30); display((i[6]& 0x0f) +0x30); checkday(i[3]); address(0x80); if(i[2]>0b00010010) { i[2]=i[2]-0b00010010; display(((i[2] & 0b00110000)>> 4)+0x30); display((i[2] & 0x0F) + 0x30); display(':'); dd=0; } else { display(((i[2] & 0b00110000)>> 4)+0x30); display((i[2] & 0x0F) + 0x30); display(':'); dd=1; } display(((i[1] & 0xF0) >> 4)+0x30); display((i[1] & 0x0F) + 0x30); display(':'); display(((i[0] & 0xF0) >> 4)+0x30); display((i[0] & 0x0F) + 0x30); check(); } unsigned char Read(unsigned char i) { unsigned char Read; if(i==6) ACKDT=1; //value transmitted & say stop to slave else ACKDT=0; // value not transmitted completely, keep on transmit while(BF==0); //waiting for value, will b 1 if data enters Read=SSPBUF; SSPOV=0; //no overflow SSPIF=0; //interrupt 0 ACKEN=1; //ack seq enable bit return(Read); } void main() { unsigned char i,read[7]; PORTD=0X00; PORTE=0X00; TRISE=0x00; TRISD=0x00; ADCON1=0X06; SMP=1; //MAKE SAMPLE BIT AS 1 SSPCON=0x28; SSPCON2=0b00000000; type(); on(); while(1) { start(); send(0xD0);//address of slave send(0x00); restart(); send(0xD1); for(i=0;i<7;i++) { RCEN=1; read=Read(i); } stop(); conv(read); } } |
|
相关推荐
13个回答
|
|
是我错了,还是这是错的?
以上来自于百度翻译 以下为原文 Am I wrong, or this is wrong? while(ACKSTAT==1); //will be 0 if ack received from slave @QHB ... |
|
|
|
|
|
|
|
你不能等待“ACK”:你只是在字节被传输之后检查它的状态。
以上来自于百度翻译 以下为原文 You must not "wait" for ACK: you just check its state after the byte has been transmitted. |
|
|
|
|
|
|
|
两点。[1]正如Dario所说,在您的发送函数中,等待ACK位是不正确的。您应该读取一次,如果它不是ACK,则等待较长时间不会使它变成ACK。[2]您的读取函数没有等待ACKEN位再次变低,因此您正在尝试启动第二个ACK。阅读之前,第一个已经完成。
以上来自于百度翻译 以下为原文 Two points. [1] As Dario stated, in your send function, waiting for the ACK bit is incorrect. You should read it once, if it is not an ACK, waiting longer will NOT make it change into an ACK. [2] Your read function is not waiting for the ACKEN bit to go low again, so you are trying to start the second read before the first one has finished. |
|
|
|
下面是我根据您的指令修改的代码。请帮帮我。为I2C编写正确的代码并在硬件中获得正确的输出是很困难的。
以上来自于百度翻译 以下为原文 Here below is my modified code as per your instruction.. Kindly Help me.. It's feel hard to write a correct code for I2C and get a output correct in Hardware.... #include #define _XTAL_FREQ 20000000 __CONFIG(0x3F3A); #define lcd PORTD #define rs RE0 #define rw RE1 #define en RE2 int i[7]; void enable() { en=1; __delay_ms(10); en=0; __delay_ms(10); } void cmd(int a) { rs=0; rw=0; lcd=a; enable(); } void display(char c) { rs=1; rw=0; lcd=c; enable(); } void string(char *str) { while(*str) { rs=1; rw=0; lcd=*str; *str++; enable(); } } void wait() { while(SSPIF==0); SSPIF=0; } void start() { SEN=1; wait(); } void stop() { PEN=1; wait(); } void restart() { RSEN=1; wait(); } unsigned char send(unsigned char send) { if(ACKSTAT==1) SSPBUF=send; if(ACKSTAT==0) ACKSTAT=1; wait(); } unsigned char Read(unsigned char ack) { unsigned char Read; RCEN=1; while(RCEN); Read=SSPBUF; if(ack==0) ACKDT=0; else if(ack==1) ACKDT=1; ACKEN=1; while(ACKEN); return Read; } void check() { if((i[2]&0b00100000)==0) { string("AM"); } else { string("PM"); } } void conv(unsigned char i[]) { cmd(0xc0); display(((i[4]& 0x30) >>4) + 0x30); display((i[4]& 0x0f) + 0x30); display('-'); display(((i[5] & 0x10) >>4) + 0x30); display((i[5] & 0x0f) +0x30); display('-'); display(((i[6]& 0xf0) >>4) + 0x30); display((i[6]& 0x0f) +0x30); cmd(0x80); display(((i[2] & 0b00110000)>> 4)+0x30); display((i[2] & 0x0F) + 0x30); display(':'); display(((i[1] & 0xF0) >> 4)+0x30); display((i[1] & 0x0F) + 0x30); display(':'); display(((i[0] & 0xF0) >> 4)+0x30); display((i[0] & 0x0F) + 0x30); } void main() { unsigned char i,read[7]; PORTC=0X00; PORTD=0X00; PORTE=0X00; TRISE=0x00; TRISC=0X18; TRISD=0x00; ADCON1=0x06; SMP=1; SSPCON=0x28; SSPCON2=0b00000000; start(); send(0xD0); send(0x00); restart(); send(0x55); send(0x50); send(0x23); send(0x02); send(0x20); send(0x03); send(0x95); stop(); cmd(0x38); cmd(0x0E); cmd(0x01); while(1) { start(); send(0xD1); restart(); for(i=0;i<7;i++) read=Read(i); stop(); conv(read); } } |
|
|
|
你的新发送程序更糟。我猜你一点儿也不理解ACK位是如何工作的。试试这个(注意,我认为使参数名和函数名相同不是个好主意,所以我修改了名称):现在可以测试返回值,看看从节点是否确认了你发送的字节。你的7个字节,你的循环需要这样做:
以上来自于百度翻译 以下为原文 You new send routine is even worse. I guess you're not understanding how the ACK bit works at all. Try this (note, I don't think it's a good idea to make parameter names the same as the function name, so I modified the name): //send byte to I2C slave. Return 0 if ACK, 1 if NAK response unsigned char send(unsigned char send_dat) { SSPBUF=send_dat; // send the data byte wait(); // wait until data has been sent, and re have received the ACK flag return ACKSTAT; //read ACK flag, and return it. ACK=0, NAK=1 } Now you can test the return value to see if the slave acknowledged the byte you sent. //Read byte from slave. Pass 0 to send ACK after, or non-zero to send NAK unsigned char Read(unsigned char ack) { RCEN=1; //Start the read cycle while(RCEN); //wait until read cycle is complete if (ack==0) ACKDT=0; //we need to send ACK else ACKDT=1; //we need to send NAK ACKEN=1; //start the ACK/NAK cycle while(ACKEN); //wait until ACK/NAK cycle is complete return SSPBUF; //Return the value we received } Now, when you want to read your 7 bytes, your loop will need ot be like this: //Read 7 bytes from slave for(i=0;i<7;i++) read = Read(i != 6); //send ACK after each byte except the last (#6) stop(); |
|
|
|
非常感谢你的回复…我非常感谢你…让它知道它是否有效。
以上来自于百度翻译 以下为原文 Thanks a lot for your reply... I'm so thankful to you... Let you know if it works. |
|
|
|
遗憾的是,它不起作用:(请帮助我得到答案,先生……)
以上来自于百度翻译 以下为原文 Sadly it doesn't working sir :( Kindly help me to get the answer sir... |
|
|
|
调试的秘诀是将问题分解成更小的步骤。与其试图对时间进行解码,不如在已读取的每个寄存器中打印十六进制值,看看它是否有意义。如果仍然被卡住,请将整个源代码发布为现在存在的。
以上来自于百度翻译 以下为原文 The secret to debugging is to break your problem up into smaller steps. Rather than trying to decode the time, just print the hex values in each of the registers you have read and see if it makes sense. If you're still stuck, post your entire source as it exists now. |
|
|
|
好的,先生!我有疑问,请澄清先生!在MSI模块的SPI模式中,我使用了两个微控制器一个作为主机,另一个作为一个从控制器。所以,我为每个微控制器编写了单独的程序。在配置SSPSTAT、SSPCON、SSPCON2寄存器时,对于主配置为主模式的I,从从属模式配置的从属I。如果我用一个微控制器和一个串行IC(DS1307)。我应该只在微控制器上编程。因此,在配置SSPSTAT,SSPCON,SSPCON2注册我应该选择哪种模式????我将奴隶地址发送给奴隶,并在DS1307中编写和读取寄存器。那么,我应该采用哪种模式呢?我不仅要求I2C,而且我也要求SPI。这可能是没有根据你。你太有经验了。但对我来说,我是新手。所以,请帮帮我。在微控制器中,良好的理解是很重要的。
以上来自于百度翻译 以下为原文 Ok sir ! I have a doubt , please clarify sir ! In SPI mode in MSSP module i have used two micro-controller one as Master and another one as slave. So, i have written separate programs for each micro-controller. During Configure the SSPSTAT, SSPCON, SSPCON2 registers , for master i configured in Master mode, for slave i configured in slave mode. If i go with one micro-controller and one Serial IC (DS1307). I should program only on Micro-controller. So, in configure the SSPSTAT, SSPCON, SSPCON2 registers which mode i should select??? I am sending slave address to slave and write and read back the registers in DS1307. So, which mode i should go with it? Not only i am asking for I2C. I am asking for SPI too. This may be nothing according to you. Bcz you are so experienced. But for me i am newbie. So, kindly help me. Good understanding is important in micro-controllers. |
|
|
|
我不明白你的意思。PIC中的MSSP外围设备可以在SPI模式或I2C模式下工作,不是同时工作。在第一个示例中,您讨论的是SPI模式。在本主题中,您使用I2C模式与I2C设备进行通信。这与SPI完全不同。您是I2C主机,而设备(DS1307)是I2C从机。
以上来自于百度翻译 以下为原文 I don't understand what you are asking. The MSSP peripheral in your PIC can work in either SPI mode, or I2C mode, not both at the same time. In your first example, you are talking about SPI mode. In this topic, you are using I2C mode to talk to an I2C device. That is totally different to SPI. You are the I2C master, and the device (the DS1307) is the I2C slave. |
|
|
|
啊哈,我甚至没有看你的MSSP初始化,我以为你已经超出了这一点。你所拥有的就是这样。如果你查阅PIC16F87A数据表,你会发现在I2C模式下,SMP位做了与SPI模式完全不同的事情。这是“转换速率控制”,而“1”的设置禁用了这一点。SpCon=0x28将MSSP输入到I2C主模式,但它也表示:所以你的I2C时钟速度是由SSPADDYou控制的,不给SSPADD写任何东西。你没有提到你正在运行的PIC的速度。如果它是20MHz,并且你想要一个100KHz的I2C时钟,那么SSPADD应该是(20MHz/1)。0kHz)/ 4)- 1=(20000000/100000)/ 4)-1=49
以上来自于百度翻译 以下为原文 Ahhh, I didn't even look at your MSSP initialisation, I assumed you were beyond that point. All you have is this SMP=1; //MAKE SAMPLE BIT AS 1 SSPCON=0x28; SSPCON2=0b00000000; If you consult your PIC16F877A datasheet, you will see that in I2C mode, the SMP bit does something totally different to SPI mode. It is the "slew rate control", and a setting of "1" disables that. That is ok. SSPCON=0x28 puts your MSSP into I2C Master mode, but it also says: 1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) so your I2C clock speed is controlled by SSPADD You aren't writing anything to SSPADD. You don't mention what speed you are running your PIC at. If it is 20MHz, and you want a 100kHz I2C clock, then SSPADD should be ((20MHz / 100kHz)/4)-1 = (20000000 / 100000)/4)-1 = 49 |
|
|
|
只有小组成员才能发言,加入小组>>
5195 浏览 9 评论
2013 浏览 8 评论
1937 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3185 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2240 浏览 5 评论
750浏览 1评论
636浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
521浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
647浏览 0评论
548浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-2 13:54 , Processed in 2.106776 second(s), Total 100, Slave 84 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号