(转贴)我用GCC写的AT24C64接口程序,已调试通过,与大家分享
我前几天发表了一个贴子,是关于ATMEGA的TWI编程的。现在转贴一下21icc上mxh0506发表的贴子。我调试了一下,没有错误。
我就基本按照他的程序写的,贴出来与大家共享。
非常感谢mxh0506。支持阿莫。
// AT24C64 support functions using ATMEGA's TWI
// pin-WP is hard-wired to GND
// fuctions work better outside interrupt routines
// by MXH, 2003/07/30
#include "DStruct.h"
#include <avr/twi.h>
// CONSTANTS DEFINITION FOR EEPROM
#define EEADDR 0
#define EEWR 0
#define EERD 1
// TWINT *NOT* set after STOP condition is sent
// check status?
// TWSTO is cleared by hardware
#define TwiStop() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO)
#define TwiStart() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA)
#define TWI_STATUS (TWSR & 0xF8)
BYTE byEEWait;
//////////////////////////////////////////////////////////////////////////
// implementation
BOOL EEPStart(BYTE addr, BOOL bWrite)
{
byEEWait = 10; // 90~100ms
poll_ack:
TwiStart();
while (!(TWCR & (1<<TWINT))){ // wait
if ( byEEWait == 0 ){
return FALSE;
}
}
if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START))
goto poll_ack;
//byEEWait = 3; // 20~30ms
// send SLA+R/W
TWDR = addr | bWrite;
TWCR = (1<<TWINT)|(1<<TWEN);
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 ){
TwiStop();
return FALSE;
}
}
if( EEWR == bWrite ){ // MT mode
//if(TWI_STATUS != TW_MT_SLA_ACK)
switch(TWI_STATUS){
case TW_MT_SLA_ACK:
break;
case TW_MT_SLA_NACK:
goto poll_ack;
default:
TwiStop();
return FALSE;
}
}else{ // MR mode
if(TWI_STATUS != TW_MR_SLA_ACK)
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
BYTE EEPWrite( WORD uiAddress, WORD uiLen, void *pBuf ) //using 0
{
unsigned int i,j,uiCnt;
if( uiLen == 0 ) return 0;
uiCnt = 0;
// uiEnd = uiAddress + uiLen;
i = uiAddress;
do{
if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in
return 0;
}
TWDR = (BYTE)((i>>8)&0x00ff); // MSB of address
TWCR = (1<<TWINT)|(1<<TWEN);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if(TWI_STATUS != TW_MT_DATA_ACK){
return FALSE;
}
TWDR = (BYTE)(i&0x00ff); // LSB of address
TWCR = (1<<TWINT)|(1<<TWEN);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if(TWI_STATUS != TW_MT_DATA_ACK)
return FALSE;
// write data
for( j=0; j<32; j++ ){
TWDR = ((BYTE*)pBuf);
TWCR = (1<<TWINT)|(1<<TWEN);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if(TWI_STATUS != TW_MT_DATA_ACK){
return FALSE;
}
i++;
uiCnt++;
if(( 0 == i%32 )||( uiCnt == uiLen )){
TwiStop();
break;
}
}
}while( uiCnt < uiLen );
// while( !PollAck());
return 1;
}
//////////////////////////////////////////////////////////////////////
//
BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf )
{
UINT i;
if ( uiLen == 0 ) return 0;
if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in
return 0; //↑
} // not RD but write device address to the chip
TWDR = (BYTE)(( uiAddress >> 8) & 0x00ff ); //((BYTE*)(&uiAddress)); // MSB of address
TWCR = (1<<TWINT)|(1<<TWEN);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if (TWI_STATUS != TW_MT_DATA_ACK)
return FALSE;
TWDR = (BYTE)( uiAddress & 0x00ff ); //((BYTE*)(&uiAddress)); // LSB of address
TWCR = (1<<TWINT)|(1<<TWEN);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if (TWI_STATUS != TW_MT_DATA_ACK)
return FALSE;
if(!EEPStart(0xA0+EEADDR,EERD)){ //PollAck()){
return 0; //↑
}// ??? how to read?
for ( i=0; i<uiLen-1; i++ ){
TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWEA);
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
if (TWI_STATUS != TW_MR_DATA_ACK)
return FALSE;
((BYTE*)pBuf) = TWDR; // EEInByte();
}
TWCR = _BV(TWINT) | _BV(TWEN); // send NACK to indicate final byte
byEEWait = 3; // 20~30ms
while (!(TWCR & (1<<TWINT))){
if( byEEWait == 0 )
return FALSE;
}
//if (TWI_STATUS != TW_MR_DATA_ACK)
// return FALSE;
((BYTE*)pBuf) = TWDR;
TwiStop();
return 1;
} 能不能将原理图及实物图也上传上来。这样,我就可以将它制作成范例的形式整理到网站了。
谢谢。
本论坛支持10M的压缩包的上传的。 这部分的原理图很简单的,就是M16的SCL(PC0),SDA(PC1)引脚分别和AT24c64的SCL,SDA引脚相连,再分别接一个上拉电阻。AT24c64的地址线多少根据总共连接的芯片数而定。我只接了
AT24c64一个芯片,所以把其A0,A1,A2全部接地了。 如果sltain 画过线路图,能否上传上来? 没有线路图,做不成范例贴呢。./emotion/em018.gif 如果sltain 画过线路图,能否上传上来? 没有线路图,做不成范例贴呢。./emotion/em018.gif 这是AT24C64接口的线路图,需要说明的是:AT24c64的地址线多少根据总共连接的芯片数而定。我只接了AT24c64一个芯片,所以把其A0,A1,A2全部接地了。
点击此处下载armok011142.rar 谢谢sltian!
能不能将工作原理、可以应用在什么场合、输出结果、及某些注意事项稍为描述一下? 抱歉不断提要求,因为我也经验不足,呵呵。 我很菜的,刚开始学习AVR单片机,我就是想练习一下M16的TWI接口编程,应用的场合有很多,主要是你需要实时的将单片机监测的数据存储起来,等到需要的时候再将数据读出来。然后再分析数据,有点类似于黑匣子的功能。我用的就是监测的功能。这个程序只是一个读写的例子,用的时候可以把它作为子程序调用。
注意的问题就是抗干扰的问题。有可能AT24C64读取或者存取的时候指针受干扰跑飞了。
这个问题不好解决,我也没什莫经验。
为了支持阿莫,我贴出来就是让大家用的时候直接用它做子程序读写AT24C64。
主要的解释已经在程序里面了。 谢谢sltian! 刚才讨论了一下,我们目前的范例应用,都是以实现特定目的作为主题的。
如果只是一个类似子程序的功能,不太符合应用范例的要求----- 我们担心收录了太多这种的内容后,就会影响范例应用的针对性。
所以,先缓一下,等你有空做出一个实际的小应用(那怕是驱动LED灯也算),才好处理。详细的要求,可以到 http://www.ouravr.com/app_index.html 看一下这些应用范例的内容。
又要说不好意思。网站刚成立,很多细节都需要摸索,希望你能支持一体谅。谢谢。 没有关系呀,我知道了。我从网站上学习了好多东西。希望阿莫继续努力 如果你有空,能否将它做成一个小应用? 这么好的代码,浪费了可惜啊。谢谢。 好的。 不够通用,没有抽象出来,新手看了这个还是会头晕的 对。所以,只有整理成应用范例的形式,对其它人才更有参考价值。 程序一大串,应该有个说明文档,再加点必要注释,尤其是用到的
标准C里没有的库函数,简单说明一下,可读性会强很多。方便其
他人应用。 恩人呀!!!就是它了!!! ERRORS:67 Warnings:24 #include "DStruct.h"
这个库函数 怎样定义的 能把所有代码给出来吗 AT24CXX的资料里,只介绍到24C32 到24C64的分资料写的很模糊.
不知楼主能不能在这里介绍一下.
我找了好多地方,都没有详细介绍的.
我的AT24C04 调试过去了.可是24C64在页写的地方有点错误
请楼主指教 不知道各位大虾们怎么写程序,我写程序都会写注释,不然自己写的程序,一个月后,自己都会看不懂,尤其很大的程序! void read_sc(uchar ip,uchar * sc)
{
ReadPage24C32(SC_ADDRESS+((uint)ip<<4),32,sc);
}
int write_sc(uchar ip,uchar * sc)
{
uchar buf1,buf2;
uchar i;
for(i=0;i<32;i++)buf1=sc;
WritePage24C32(SC_ADDRESS+((uint)ip<<4),buf1,32);
read_sc(ip,buf2);
for(i=0;i<32;i++)
{
if(buf1!=buf2)return -1;
}
return 0;
}
怎么通过这个读写数据呢 版主教教我啊 可惜不是中断处理 好贴,顶一个,大家多多交流阿! #include "DStruct.h"
#include <avr/twi.h>
这两个都没有给出,运行不能通过,是怎么回事啊? 怎么这么不好阅读呢 写的太棒了,正是我要的,但有一句有点小问题,也许我没理解:if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START))
似乎当写为:if ((TWI_STATUS != TW_START)||(TWI_STATUS != TW_REP_START))
如不对,请楼主不要生气。
发送程序,芯片资料中可参考,但接收程序及其反回的状态代码,资料中并不详,这里全有了,太好了。
我特别注意到的是:BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf )
{
UINT i;
if ( uiLen == 0 ) return 0;
if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in
return 0; //↑
} // not RD but write device address to the chi
。。。。。。我原先写的大意是:if(!EEPStart(0xA0|EEADDR,EERD)),老跑不通,明师在这里指点了。盗下来,盗下来,谢谢了,感谢被盗者的幸劳。 #include "DStruct.h"
#include <avr/twi.h>
兴奋之余,给弟兄们粗略地解释一下:这两个头文件可能是楼主自定义的两个头文件,无非是定义数的结构和给TWI中的寄存器换个名称而已。比如说:#define TWI_STATUS TWSR 再比方说:有一个延时函数必在头文件中,其中有个变量为 byEEWait,也有可能这个变量在某个时间中断里,它在递减。这样如果发送或接收超时的话要报警的,至于各人的需要,要在这个程序上改动的。
还有从程序中看出,一次性最多只可发送32个数据。这些可以看看芯片资料。
说上面的这些废话,主要是报达一下对楼主的一点谢意。我也公开一点自己的想法。不知有没有人谢我。不谢没事,别骂就行,哈哈。 好贴啊 不錯,正在找這方面的,謝謝了! 学些了 MARK iic程序怎么那么长,看着都郁闷。
页:
[1]