感谢傻孩子,你的X档案救我出苦海,哈哈
前两周买了本你的书,读了一下很爽。参考了你写工程结构的twi程序,想做m8双机通信。protues上仿真通过,烧板子上没调通,比较郁闷,想想twi就那么回事,就偏偏调不好。找了N多原因,如上拉,时钟,线路,程序怎么也没找出问题,后来干脆用主机程序读写24C64看看能否通过,结果都是一个奇怪的问题:
主机能寻址到从机,从机也能被寻址到,但接着问题就来了,主机竟然重新发起start 信号,对状态机
//清零控制位,方便后面的操作,同时应将TWINT清零,否则将等同
//“向TWINT写1清零”操作,将误启动总线,陷阱
TWCR &= ~(1 << TWINT)|(1 << TWEA)|(1 << TWSTO)|(1 << TWSTA);
case SLA_ADDRESS_ACK:
if(flag2 == 0) //发送单字节数据
{
TWDR = byte;
}
else if(flag2 == 1)//发送多字节数据
{
TWDR = *(data + data_counter);
data_counter += 1;//发送数据串的第一个数据
}
//sla_w ack
break;
TWCR |= (1 << TWEN)|(1 << TWINT);
中发送数据的操作不理睬,检查了下我的操作没有问题吧。如果我在从机寻址应答后发送一个stop信号则能够正常响应。但是响应过后马上又一个start信号
坦白地说,这个问题搞了好久,好痛苦。
昨晚看了你的X档案,提到对TWCR寄存器的如
TWCR |= (1 << TWEN)|操作实质是一个读-修改-写的过程(在你书上看到过,但只重视了twint位的影响)。今天再次调试了下,正常发现进入case SLA_ADDRESS_ACK: 操作完毕后,执行
TWCR |= (1 << TWEN)|(1 << TWINT);状态寄存器的标志位为0x10,说明TWSTA位早已神不知鬼不觉地置一了,火大,在
TWCR |= (1 << TWEN)|(1 << TWINT);前加一句TWCR &= ~(1 << TWSTA);之后一切搞定,通信成功的指示灯终于亮了。
即便是这样小小的问题,要深入思考才会有结果。像之前一样的无头苍蝇真是太可悲了。
http://cache.amobbs.com/bbs_upload782111/files_22/ourdev_510299.jpg
波形 (原文件名:PIC_1866.jpg)
http://cache.amobbs.com/bbs_upload782111/files_22/ourdev_510300.jpg
现在终于知道问题的根源了 (原文件名:PIC_8088.jpg) MARK 感觉你遇到的问题可能不是那么简单…… 才发现2楼的笑容有点那个~~ mark 坦白地说我还不知道为什么start会置一,但问题就是出在这里,把新加的一句请零start注释掉就不能通信了。
还请傻孩子指教。我的操作都是按常规来的,被这问题卡了好久。 把你的通讯状态机贴出来……
最好能做一个 复现 问题的最小化工程……不然无法帮你分析啊…… 原来是我的位操作出了问题,
在进入twi中断的时候我是这样写的:
TWCR &= ~(1 << TWINT)|(1 << TWEA)|(1 << TWSTO)|(1 << TWSTA);
结果是后面的位无法清零。
加个大括号
TWCR &= ~((1 << TWINT)|(1 << TWEA)|(1 << TWSTO)|(1 << TWSTA)); 就好了。
谢谢傻孩子,菜鸟的问题总是比较雷人。 不过至少通过这个问题,让你对TWI TWCR寄存器有了一个比较深刻的认识。
页:
[1]