|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機 | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計 | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
//24c16應(yīng)用c51程序 |
| 作者:linping 欄目:單片機 |
//24C16應(yīng)用c51程序 /*此程序所有功能正常,適合dy3st.pcb*/ /*1。2005/3/20添加6v電源處理*/ /*cpu用89c55wd,晶振22.1184MHZ*/ #pragma code #include <reg52.h> #include <math.h> #include <ABSACC.h> #include <intrins.h> #define byte unsigned CHAR #define word unsigned int #define uCHAR unsigned CHAR #define uint unsigned int #define TRUE 1 #define FALSE 0 #define HIGH 1 #define LOW 0 /*-------------24C16-----------------------------*/ sbit SCL = P1^1; sbit SDA = P1^2; void delay(uint x,uint y) { uint i,j; for(i=0;i<=x;i++) { for(j=0;j<=y;j++) { _nop_(); _nop_(); } } } void wait(void) { byte i=50; for(i=0;i<8;i++); } void delay10(uint x) { uint i=0; for(i=0;i<x;i++) _nop_(); } void I_init(void) { SCL = HIGH ; SDA=HIGH ; wait(); } void I_start(void) { SCL = HIGH ; wait(); SDA=LOW; wait(); SCL=LOW; wait(); } void I_stop(void) { SDA=LOW; wait(); SCL = HIGH ; wait(); SDA=HIGH ; wait(); SCL=LOW; wait(); } void I_send(byte a) { byte i; for(i=0;i<8;i++) { if(a & 0x80) SDA=HIGH; else SDA=LOW; a=(a<<1); SCL = HIGH ; wait(); SCL=LOW; wait(); } SDA=HIGH; wait(); SCL = HIGH ; wait(); SCL=LOW; wait(); } byte I_receive(void) { byte a=0; byte i; for(i=0;i<8;i++) { a = a*2; SCL = HIGH ; wait(); if(SDA) a |= 1; SCL=LOW; wait(); } SDA=HIGH; wait(); return(a); } void I_addres_wri(byte ds,byte x,byte a) { I_start(); I_send(ds); I_send(x); I_send(a); I_stop(); delay10(0x500); } byte I_addres_red(byte ds,byte x) { byte a; I_start(); I_send(ds); I_send(x); I_start(); I_send(ds+1); a=I_receive(); I_stop(); return(a); } void wri_n(uCHAR z,uCHAR * x,uCHAR y,byte ds)/*z:24c64addr,x,rom or ram or xdata addr ds:寫進24C16的分區(qū),第1區(qū)256b,ds=0xa0;第2區(qū)256b,ds=0xa2 第3區(qū)256b,ds=0xa4;第4區(qū)256b,ds=0xa6 第5區(qū)256b,ds=0xa8;第6區(qū)256b,ds=0xaa 第7區(qū)256b,ds=0xac;第8區(qū)256b,ds=0xae*/ { uCHAR i; uCHAR a; for(i=0;i<y;i++) { a=*(x+i); I_addres_wri(ds,z+i,a); } } void rea_n(uCHAR z,uCHAR * x,uCHAR y,byte ds)/*z:24c64addr,x,rom or ram or xdata addr*/ { uCHAR i; for(i=0;i<y;i++) { *(x+i)=I_addres_red(ds,z+i); } } void main() { rea_n(7,0x8000,7,0xa8); wri_n(0,0x8000,7,0xa8); } //以上程序調(diào)試正常,希望初學(xué)者有所幫助 |
| 2樓: | >>參與討論 |
| 作者: qjy_dali 于 2005/5/31 13:45:00 發(fā)布:
調(diào)試正常?! 本人當初也曾對小巧玲瓏的I2C進行過學(xué)習(xí),EEPROM也是我第一個開刀的,所以看到這個程序突然來了點興趣。再加上樓主用了C51而不是匯編(匯編我忘的差不多了),所以看了下去,F(xiàn)發(fā)表點見解: (1). 主機接收時我怎么沒有看見應(yīng)答位操作(也就是第9位)?如果真是這樣,那么你這個程序也只能是一次讀一個字節(jié);使用標準的I2C連續(xù)讀命令肯定要出錯。 你也許會反對,為什么我讀一個字節(jié)沒有錯呢?那是因為你前面的I2C命令發(fā)的都是正確的;在你接收到一個完整的字節(jié)(8個位)時,EEPROM會釋放SDA線,如果你在第9位使SDA為高,它就不再輸出(徹底釋放SDA),以便你控制SDA線發(fā)STOP命令;如果你在第9位使SDA為0,則EEPROM會認為你還想接收,于是繼續(xù)控制SDA線以便發(fā)送下一個字節(jié)。但是你所編寫的主機作為接收方在第9位時直接發(fā)送了STOP位!這樣,接收的字節(jié)還是正確的,但是你是以非正常的時序結(jié)束了I2C總線上的活動。 所以,如果你使用EEPROM的連續(xù)讀命令時,是無法正常讀取的,只有第1個字節(jié)是正常結(jié)果。在你上面的程序基礎(chǔ)上,如果要讀取EEPROM的許多單元,你只能多次調(diào)用你的字節(jié)讀取函數(shù)來循環(huán)實現(xiàn)了。 。2). C語言的風格還不是很好。比如,函數(shù)的前面沒有函數(shù)的介紹,輸入輸出參數(shù)說明。變量的命名有點隨便了。注釋相對而言少了點。 。3). 總的來說,I2C編寫的框架我覺得還是非常好的。對于移植可能會比較方便。宏的使用也比較好,比如說HIGH和LOW的運用。 目前就能說出這么三點,如有不當請指正 ^_^ |
|
| 3樓: | >>參與討論 |
| 作者: qjy_dali 于 2005/5/31 15:54:00 發(fā)布:
樓主對于I2C的應(yīng)答幀還不是很清楚 其實在I2C的總線操作里,一個字節(jié)的傳輸后必有應(yīng)答幀。應(yīng)答幀分為應(yīng)答和非應(yīng)答,說白了也就是一個位0與位1的區(qū)別罷了。決定應(yīng)答還是非應(yīng)答的總是接收方,但是提供應(yīng)答時鐘信號的總是主機。 |
|
| 4樓: | >>參與討論 |
| 作者: linping 于 2005/5/31 17:11:00 發(fā)布:
謝謝關(guān)注 首先謝謝qjy_dali 朋友的關(guān)注,這段程序是從一個項目里裁減的,所以注釋,格式等隨便了些,功能請相信是正常的,我的目的是給剛學(xué)習(xí)i2c的朋友一點參考,先讓他調(diào)出結(jié)果,再豐富完善自己的功能。 另外我做過24C32,24C64,24C256等的程序,都調(diào)試正常,也用在了具體的項目里。還有也做過ATMEGA128L的硬件i2c接口讀寫24C256的匯編程序,調(diào)試正常,有興趣的朋友可互相交流。 再次謝謝qjy_dali 的關(guān)注,希望大家共同提高! |
|
| 5樓: | >>參與討論 |
| 作者: sdyxm21 于 2005/6/1 9:06:00 發(fā)布:
呵呵,發(fā)表一下自己的感想! 樓主是做過不少東西了啊,所以有許多經(jīng)驗,而且值得贊賞的是可以把自己勞動的成果拿出來讓大家分享,在這里我代表那些剛剛起步的愛好者說一聲:謝謝了! |
|
| 6樓: | >>參與討論 |
| 作者: youngboy 于 2005/6/14 21:02:00 發(fā)布:
請教摟主 關(guān)于i/o虛擬i2c的程序 我現(xiàn)在要用ATMEGA128L的I/O口模擬I2C傳輸 訪問EEPROM 24C16 不知道怎么實現(xiàn),剛接觸i2c,是不是要按照I2C的協(xié)議在I/O口輸出時序不同的電瓶呀? 謝謝 能不能詳細地介紹一下。 |
|
| 7樓: | >>參與討論 |
| 作者: zizzfish 于 2005/6/14 22:03:00 發(fā)布:
也可以用24C01的程序訪問24C16的。 只要: ds:寫進24C16的分區(qū),第1區(qū)256b,ds=0xa0;第2區(qū)256b,ds=0xa2 第3區(qū)256b,ds=0xa4;第4區(qū)256b,ds=0xa6 第5區(qū)256b,ds=0xa8;第6區(qū)256b,ds=0xaa 第7區(qū)256b,ds=0xac;第8區(qū)256b,ds=0xae*/ |
|
| 8樓: | >>參與討論 |
| 作者: qjy_dali 于 2005/6/14 23:20:00 發(fā)布:
youngboy為什么要用虛擬I2C呢? ATMEGA128L是有硬件I2C總線的,只是ATMEL把它叫做TWI接口。 |
|
| 9樓: | >>參與討論 |
| 作者: qjy_dali 于 2005/6/14 23:22:00 發(fā)布:
何立民寫過一本I2C的書,很早,但很好! 從那本書中,我受益非淺。 |
|
| 10樓: | >>參與討論 |
| 作者: 雷風 于 2005/6/14 23:32:00 發(fā)布:
這里有一個比較另類的i2c程序,注意看接受和發(fā)送函數(shù) 應(yīng)該說用在一些情況下是有道理的 如果哪位看出錯誤請不吝指教 注意看接受和發(fā)送函數(shù)主函數(shù)(最下面),利用了協(xié)議中7位地址格式的用法 /********************************************************** I2C主機總線驅(qū)動程序。不含仲裁程序,只允許總線上有從設(shè)備。 速率5Kbit/s。 全部子程序以SCL=0,SDA=1結(jié)束。 **********************************************************/ #include<nsys.h> #define SCL P1_3 #define SDA P1_4 #define SPD 10 //速率設(shè)置。 10=5kbit/s /******************************************** I2C總線初始化 ********************************************/ void initI2C() { SCL=0; SDA=1; } /******************************************** 主機開始標志位生成子程序 ********************************************/ void I2C_START() { SDA=1; SCL=1; delay(SPD/2); SDA=0; delay(SPD/2); SCL=0; delay(SPD/2); 子程序 SDA=1; delay(SPD/2); } /******************************************** 主機停止標志位生成子程序 ********************************************/ void I2C_STOP() { SDA=0; SCL=1; delay(SPD/2); SDA=1; delay(SPD/2); SCL=0; delay(SPD); } /******************************************* 主機應(yīng)答位生成子程序 bit ack:1-應(yīng)答 0-不應(yīng)答 *******************************************/ void I2C_ACK(bit ack)//ack: 1-ack 0-do not ack { SCL=0; SDA=~ack; delay(SPD/2); SCL=1; delay(SPD); SCL=0; delay(SPD/2); SDA=1; delay(SPD/2); } /******************************************* 主機傳輸數(shù)據(jù)位生成子程序 unsigned CHAR tx:待傳輸?shù)淖止?jié) *******************************************/ void I2C_TXDATA(unsigned CHAR tx) { unsigned CHAR i; unsigned CHAR tmp=0x80; for (i=0;i<8;i++) { SCL=0; delay(SPD/2); if (tx&tmp) //該位為1送SDA=1 SDA=1; else //該位為0送SDA=0 SDA=0; tmp=tmp>>1; delay(SPD/2); SCL=1; delay(SPD); SCL=0; } delay(SPD/2); SDA=1; delay(SPD/2); } /****************************************** 主機接收數(shù)據(jù)位子程序 返回:接收的字節(jié) ******************************************/ unsigned CHAR I2C_RXDATA() { unsigned CHAR tmp=0x01; unsigned CHAR i; unsigned CHAR rx=0; SCL=0; SDA=1; for (i=0;i<8;i++) { SCL=1; rx=rx<<1; //接收一位后左移一位 delay(SPD/2); rx=rx|SDA; //接收 delay(SPD/2); SCL=0; delay(SPD); } SCL=0; SDA=1; } /******************************************* 主機傳輸子程序 不帶停止位 從設(shè)備無響應(yīng)自動從重傳 unsigned CHAR *tx:待傳輸?shù)臄?shù)組指針 unsigned CHAR num:待傳輸?shù)淖止?jié)個數(shù) unsigned CHAR target:目標設(shè)備地址 *******************************************/ void I2C_TX(unsigned CHAR data *tx,unsigned CHAR num,unsigned CHAR target ) { while(1) { unsigned CHAR tmp; I2C_START(); //開始位設(shè)立 I2C_TXDATA(target); //傳輸目標地址 SCL=1; delay(SPD/2); if (SDA) continue; //無響應(yīng)重傳 delay(SPD/2); SCL=0; for(tmp=0;tmp<num;tmp++) //傳輸數(shù)據(jù)位 { I2C_TXDATA(*(tx+tmp)); SCL=1; delay(SPD/2); if (SDA) break; //無響應(yīng)重傳 delay(SPD/2); SCL=0; delay(SPD/2); if (tmp==num-1) { SDA=1; return; } } } } /**************************************************** 主機接收子程序 不帶開始位 自動應(yīng)答 自動 |
|
| 11樓: | >>參與討論 |
| 作者: youngboy 于 2005/6/19 1:03:00 發(fā)布:
因為我們的系統(tǒng)中要用四條i2c,呵呵 |
|
| 12樓: | >>參與討論 |
| 作者: hotpower 于 2005/6/19 2:55:00 發(fā)布:
AVR自代TWI(I2C)模塊 何不用硬件模塊???不用太可惜了... |
|
| 13樓: | >>參與討論 |
| 作者: isoar 于 2005/6/19 15:04:00 發(fā)布:
看看我這個更另類的模擬I2C讀寫24C64的函數(shù) /* 說明: 本人不喜歡那么多的子程序,所以寫了這個更另類的模擬I2C讀寫24C64的函數(shù)。_nop_(); vWrite24C64();是寫函數(shù),三個參數(shù)分別是:高地址,低地址,和數(shù)據(jù); ucRead24C64();是讀函數(shù),兩個參數(shù):高地址,低地址,函數(shù)返回值為讀到的數(shù)據(jù) 因為用的是速率較快的PHILIPS的P89C669,所以程序里的_nop_();函數(shù)用得有點多,看起來有點亂 因為合并了所有的子函數(shù),程序有點長,有興趣的慢慢看啊 */ #include <REG669.h> //The Registers Define of the PHILIPS P89C669 #include <intrins.h> //include _nop_(); sbit bVSCL =P1^6; sbit bVSDA =P1^7; //-------------------AT24C64 EEPROM ----------------------------------------------------- void vWrite24C64(unsigned CHAR ucAddrH,unsigned CHAR ucAddrL,unsigned CHAR ucData) { unsigned CHAR ucBitCounter; unsigned CHAR ucSentByte; //vStartVirtualI2c(); bVSDA=1; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSDA=0; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); //vSendByte(uc24C64Address); ucSentByte=uc24C64Address; for(ucBitCounter=0;ucBitCounter<8;ucBitCounter++) { if((ucSentByte<<ucBitCounter)&0x80) bVSDA=1;else bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_(); } bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); //vSendByte(ucAddrH); ucSentByte=ucAddrH; for(ucBitCounter=0;ucBitCounter<8;ucBitCounter++) { if((ucSentByte<<ucBitCounter)&0x80) bVSDA=1;else bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_(); } _nop_();_nop_(); bVSDA=0; _nop_();_nop_();_nop_();_nop_(); bVSCL=1; _nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); //vSendByte(ucAddrL); ucSentByte=ucAddrL; for(ucBitCounter=0;ucBitCounter<8;ucBitCounter++) { if((ucSentByte<<ucBitCounter)&0x80) bVSDA=1;else bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_(); } _nop_();_nop_(); bVSDA=0; _nop_();_nop_();_nop_();_nop_(); bVSCL=1; _nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); //vSendByte(ucData); ucSentByte=ucData; for(ucBitCounter=0;ucBitCounter<8;ucBitCounter++) { if((ucSentByte<<ucBitCounter)&0x80) bVSDA=1;else bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_(); } _nop_();_nop_(); bVSDA=0; _nop_();_nop_();_nop_();_nop_(); bVSCL=1; _nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); //vStopVirtualI2c(); _nop_();_nop_();_nop_();_nop_(); bVSDA=0; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSDA=1; _nop_();_nop_();_nop_();_nop_(); } unsigned CHAR ucRead24C64(unsigned CHAR ucAddrH,unsigned CHAR ucAddrL) { unsigned CHAR ucBitCounter; unsigned CHAR ucSentByte; unsigned CHAR ucReceiveData; //vStartVirtualI2c(); bVSDA=1; _nop_();_nop_(); bVSCL=1; _nop_();_nop_();_nop_();_nop_(); bVSDA=0; _nop_();_nop_();_nop_();_nop_(); bVSCL=0; _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); | |
| 14樓: | >>參與討論 |
| 作者: qjy_dali 于 2005/6/20 23:00:00 發(fā)布:
樓上的兄弟,你的nop把我看暈了... |
|
| 15樓: | >>參與討論 |
| 作者: isoar 于 2005/6/20 23:51:00 發(fā)布:
用ue查找替換一下嘛,我給你換了 /* 說明: 本人不喜歡那么多的子程序,所以寫了這個更另類的模擬I2C讀寫24C64的函數(shù)。_nop_(); vWrite24C64();是寫函數(shù),三個參數(shù)分別是:高地址,低地址,和數(shù)據(jù); ucRead24C64();是讀函數(shù),兩個參數(shù):高地址,低地址,函數(shù)返回值為讀到的數(shù)據(jù) 因為用的是速率較快的PHILIPS的P89C669,所以程序里的_nop_();函數(shù)用得有點多,看起來有點亂 因為合并了所有的子函數(shù),程序有點長,有興趣的慢慢看啊 */ #include <REG669.h> //The Registers Define of the PHILIPS P89C669 #include <intrins.h> //include _nop_(); #define nop2(); _nop_();_nop_(); #define nop4(); _nop_();_nop_();_nop_();_nop_(); sbit bVSCL =P1^6; sbit bVSDA =P1^7; //-------------------AT24C64 EEPROM ----------------------------------------------------- void vWrite24C64(unsigned CHAR ucAddrH,unsigned CHAR ucAddrL,unsigned CHAR ucData) { unsigned CHAR ucbitCounter; unsigned CHAR ucSentByte; //vStartVirtualI2c(); bVSDA=1;nop2(); bVSCL=1;nop4(); bVSDA=0;nop4(); bVSCL=0;nop4();nop4(); //vSendByte(uc24C64Address); ucSentByte=uc24C64Address; for(ucbitCounter=0;ucbitCounter<8;ucbitCounter++) { if((ucSentByte<<ucbitCounter)&0x80) bVSDA=1;else bVSDA=0; nop2(); bVSCL=1; nop4(); bVSCL=0; nop2(); } bVSDA=0;nop2(); bVSCL=1;nop4(); bVSCL=0;nop4();nop4(); //vSendByte(ucAddrH); ucSentByte=ucAddrH; for(ucbitCounter=0;ucbitCounter<8;ucbitCounter++) { if((ucSentByte<<ucbitCounter)&0x80) bVSDA=1;else bVSDA=0; nop2(); bVSCL=1; nop4(); bVSCL=0; nop2(); }nop2(); bVSDA=0;nop4(); bVSCL=1;nop2(); bVSCL=0;nop4();nop4(); //vSendByte(ucAddrL); ucSentByte=ucAddrL; for(ucbitCounter=0;ucbitCounter<8;ucbitCounter++) { if((ucSentByte<<ucbitCounter)&0x80) bVSDA=1;else bVSDA=0; nop2(); bVSCL=1; nop4(); bVSCL=0; nop2(); }nop2(); bVSDA=0;nop4(); bVSCL=1;nop2(); bVSCL=0;nop4();nop4(); //vSendByte(ucData); ucSentByte=ucData; for(ucbitCounter=0;ucbitCounter<8;ucbitCounter++) { if((ucSentByte<<ucbitCounter)&0x80) bVSDA=1;else bVSDA=0; nop2(); bVSCL=1; nop4(); bVSCL=0; nop2(); }nop2(); bVSDA=0;nop4(); bVSCL=1;nop2(); bVSCL=0;nop4();nop4(); //vStopVirtualI2c();nop4(); bVSDA=0;nop2(); bVSCL=1;nop4(); bVSDA=1;nop4(); } unsigned CHAR ucRead24C64(unsigned CHAR ucAddrH,unsigned CHAR ucAddrL) { unsigned CHAR ucbitCounter; unsigned CHAR ucSentByte; unsigned CHAR ucReceiveData; //vStartVirtualI2c(); bVSDA=1;nop2(); bVSCL=1;nop4(); bVSDA=0;nop4(); bVSCL=0;nop4();nop4(); //vSendByte(uc24C64Address); ucSentByte=uc24C64Address; for(ucbitCounter=0;ucbitCounter<8;ucbitCounter++) { if((ucSentByte<<ucbitCounter)&0x80) bVSDA=1;else bVSDA=0; nop2(); bVSCL=1; nop4(); bVSCL=0; nop2(); }nop2(); bVSDA=0;nop2(); bVSCL=1;nop4(); bVSCL=0;nop4();nop4(); //vSendByte(ucAddrH); ucSentByte=ucAddrH; &nb |
|
| 16樓: | >>參與討論 |
| 作者: hotpower 于 2005/6/21 發(fā)布:
樓上的另類很漂亮,但流水帳記得讓人心煩理不出頭緒 |
|
| 17樓: | >>參與討論 |
| 作者: isoar 于 2005/6/21 0:04:00 發(fā)布:
那么寫只是不想看到程序里那么多的I2C子函數(shù)調(diào)來調(diào)去的 關(guān)鍵還是I2C的協(xié)議和時序,如果你心里有I2C協(xié)議和時序(心里沒有你就對照著I2C協(xié)議和時序看),從頭到尾一遍就寫下來了。 |
|
| 18樓: | >>參與討論 |
| 作者: isoar 于 2005/6/21 0:29:00 發(fā)布:
“復(fù)用”看你怎么解了,就兩個函數(shù)用到程序中粘貼一下就可以了 也許會浪費些程序存儲空間,誰讓現(xiàn)在芯片的程序存儲空間都大呢?我總覺得填不滿,呵呵。 |
|
| 19樓: | >>參與討論 |
| 作者: 漓源 于 2010/12/24 13:50:41 發(fā)布:
我買的都是正品24C16,機子運行后步進電機還是不能正常動起來,只是電機發(fā)出|嘟嘟|微顫動狀態(tài)。請問是否與我做程序有關(guān),需要如何解決? |
|
|
|
| 免費注冊為維庫電子開發(fā)網(wǎng)會員,參與電子工程師社區(qū)討論,點此進入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號 |