完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
设备:PIC16F83XC8:V1.44冻结外围设备?在那里。我遇到了一些问题,我想和你讨论一下。我用PIC16F83作为I2C从机,试图实现I2C协议,发现如果在I2C ISR中设置了BP,模块NACK就要掌握。如果没有BP,只需让它自由运行,模块ACK就可以了。根本没有代码改变。我猜:BP也停止了外围设备的时钟,冻结了I2C模块发送ACK。根据手册:如果地址匹配,并且BF和SSPV位是清晰的,则会发生以下事件:A)SSPSR寄存器值被加载到SSPBUF寄存器中。B)设置缓冲器全位BF。C)产生ACK脉冲。D)MSP中断标志位,PIP1寄存器的SSPIF,设置在F上。第九SCL脉冲的边沿(中断产生,如果启用)。这意味着,如果程序在BP停止,ACK/NACK信号已经被I2C模块发送。有第三的可能性吗?谢谢您。
以上来自于百度翻译 以下为原文 Device: PIC16F883 XC8: v1.44 Freeze Peripheral?: enabled Hi, there. I run into some case that I want to discuss it with you. I used PIC16F883 as an I2C slave, trying to implement I2C protocol. I found that if bp is set in the I2C ISR, module nack to master. If there is no bp, just have it free run, module ack to master. No code changed at all. My guess: the bp also stops peripheral's clock, freezes i2c module to send ack. But as per manual: If the addresses match, and the BF and SSPOV bits are clear, the following events occur: That means, if the program stops at bp, the ack/nack signal has already been sent by i2c module. Is a third possibility there? Thank you. |
|
相关推荐
5个回答
|
|
甚至不能猜测,除非你显示你的代码,并确切地指出你放置断点的位置。
以上来自于百度翻译 以下为原文 Can't even guess unless you show your code and indicate exactly WHERE you are placing your breakpoint. |
|
|
|
这是代码,左边是I2C的ISR,右边是ISR。如果需要任何信息,请告诉我,我会把它张贴在上面。
以上来自于百度翻译 以下为原文 Here is the code, the left is ISR of i2c, right is ISR. If need any information, please tell me, I will post it on. Attached Image(s) |
|
|
|
您只显示了一小部分代码,但是什么看起来不太好。测试SSPSTAT中的开始和停止位的代码是愚蠢的。它试图清除只读的比特。开始位将被设置为整个事务,因此每次获得SSP中断时,您将在IF(I2CSTART)块中执行代码。简而言之,我认为您的代码非常笨拙,只是运气好,没有断点就可以工作。St你重新思考整个逻辑,或张贴你所有的代码,这样我们就可以更好地了解你想要做什么。
以上来自于百度翻译 以下为原文 You've only shown a small bit of your code, but what is there does not look good. The code testing the start and stop bits in SSPSTAT is silly. It's trying to clear read only bits. The start bit will be set for a whole transaction, so every time you get an SSP interrupt, you will be executing the code in the if(i2cStart) block. In short, I think your code is very buggy, and it's just luck that it works at all without the breakpoint. I'd suggest you rethink the whole logic, or post ALL your code so we can see better what you are trying to do. |
|
|
|
这里是完整的I2C ISR代码:谢谢。
以上来自于百度翻译 以下为原文 Here is Whole i2c ISR code: #include #include "type.h" #include "dio.h" #include "***s.h" //#include "sys.h" #define i2c_Clock_Stretch 1 typedef struct{ BYTE RegFlag; BYTE DataFlag; } FlagType; FlagType Flag; #define i2c_SlaveAddr 0x60 BYTE i2c_RegNo=0; //current regNo for R/W BYTE i2c_RamBuf[4]; //parameter forwrite operation BYTE*i2c_Buf; int *i2c_WBuf; #define i2cStart (SSPSTATbits.I2C_START == 1) #define i2cStop (SSPSTATbits.I2C_STOP == 1) #define i2cWriteCmd (SSPSTATbits.R_W == 0) #define i2cReadCmd (SSPSTATbits.R_W == 1) #define i2cAddrByte (SSPSTATbits.D_A == 0) #define i2cDataByte (SSPSTATbits.D_A == 1) //====================================================== void SLI2C_ISR(void){ BYTE temp; BYTE*ptr; if(i2cStart){ SSPSTATbits.I2C_START = 0; Flag.RegFlag = 0; Flag.DataFlag = 0; temp = SSPBUF; } if(i2cStop){ SSPSTATbits.I2C_STOP = 0; Flag.RegFlag = 0; Flag.DataFlag = 0; temp = SSPBUF; } if(i2cWriteCmd){ if(i2cAddrByte){ //1st byte, Address matched temp = SSPBUF; //dummy read to clear Buf full flag Flag.RegFlag = 1; //next byte will be regNo // #if defined(i2c_Clock_Stretch) // SSPCONbits.CKP = 1; //Release SCL line // #endif } else if(i2cDataByte){ //2nd ~ bytes, data if(Flag.RegFlag){ //wait RegNo i2c_RegNo=SSPBUF; //get RegNo Flag.RegFlag = 0; i2c_Buf=&i2c_RamBuf[0]; //init buf pointer for coming data if(i2c_RegNo==SBS_OffCtrlRegNo){ SysPower_Off(); } else if(i2c_RegNo==SBS_OnCtrlRegNo){ SysPower_On(); } else{ Flag.DataFlag = 1; //if next parameter is required } // #if defined(i2c_Clock_Stretch) // SSPCONbits.CKP = 1; //Release SCL line // #endif } else if(Flag.DataFlag){ temp = SSPBUF; //ignore all coming data //*i2c_Buf++ = SSPBUF; // #if defined(i2c_Clock_Stretch) // SSPCONbits.CKP = 1; //Release SCL line // #endif } } } else if(i2cReadCmd && i2cAddrByte){ temp = SSPBUF; //dummy read to clear Buf full flag //execute Read action i2c_Buf=&i2c_RamBuf[0]; i2c_WBuf=(int*)i2c_Buf; switch(i2c_RegNo){ case ***s_TempRegNo: *i2c_WBuf = Bat_Temperature; break; case ***s_VolRegNo: *i2c_WBuf = Bat_Voltage; break; case ***s_CurrRegNo: *i2c_WBuf = Bat_Current; break; case ***s_StatusRegNo: ptr = (BYTE*)&Bat_Status; i2c_RamBuf[0]=*ptr++; i2c_RamBuf[1]=*ptr; break; default: *i2c_WBuf = 0; } SSPCONbits.CKP = 1; SSPBUF = *i2c_Buf++; while(SSPSTATbits.BF); SSPCONbits.CKP = 1; SSPBUF = *i2c_Buf; while(SSPSTATbits.BF); SSPCONbits.CKP = 1; } } //================================================================== void SLI2C_Init(void){ SSPCON = 0b00101110; //Enable I2C module, 7bits addr slave mode //SSPCON2 =0; SSPADD=i2c_SlaveAddr; //SSPMSK=0xff; Flag.RegFlag = 0; //Initlize AddFlag Flag.DataFlag = 0; //Initlize DataFlag PIE1bits.SSPIE=1; } Thank you. |
|
|
|
我认为你的宏只是混淆了这个问题。把你的ISR中的第一个块扩展到真正的代码。你的代码有缺陷,因为你认为你可以清除I2cSART。你不能,它将保持设置直到接收到停止条件。
以上来自于百度翻译 以下为原文 I think your macros are just confusing the issue. Expanding the first block in your ISR back to the real code. if((SSPSTATbits.I2C_START == 1)){ // will be true whenever the last state change was a START, not a STOP SSPSTATbits.I2C_START = 0; // Pointless. I2C_START is a read-only flag Flag.RegFlag = 0; Flag.DataFlag = 0; temp = SSPBUF; } Your code is flawed because you think you can clear I2C_START. You can't, it will stay set until a STOP condition is received. |
|
|
|
只有小组成员才能发言,加入小组>>
5265 浏览 9 评论
2044 浏览 8 评论
1961 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3221 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2271 浏览 5 评论
799浏览 1评论
692浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
627浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
691浏览 0评论
589浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-3 05:34 , Processed in 0.947796 second(s), Total 49, Slave 44 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号