|
|||||||||||
| 技術交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術 | 電源技術 | 測控之家 | EMC技術 | ARM技術 | EDA技術 | PCB技術 | 嵌入式系統(tǒng) 驅動編程 | 集成電路 | 器件替換 | 模擬技術 | 新手園地 | 單 片 機 | DSP技術 | MCU技術 | IC 設計 | IC 產業(yè) | CAN-bus/DeviceNe |
一個利用串口自發(fā)自收的完整的C源程序 |
| 作者:baipengwei 欄目:單片機 |
1)IO分配: P1.0——P1.3 :開關量低電平輸入; P1.4——P1.7 :開關量有輸入標志; P3.2 : 691看門狗輸入 2)功能描述: 兩個同樣的板子,當其中有一個板子,開關量有輸入時候,兩塊板子上的開關量有輸入標志都動作。利用串口進行傳送。 3)電路圖: 很簡單,自己想象都可以想得出來。 4)源程序: #include <AT89x51.h> sbit input1 = P1^0 ; sbit input2 = P1^1 ; sbit input3 = P1^2 ; sbit input4 = P1^3 ; sbit WDI = P3^2 ; int i,j ; unsigned CHAR flag ; unsigned CHAR intemp,temp1,temp2,outputtemp1,outputtemp2,outputtemp3,outputtemp4 ; void initialcpu (void) { SP = 0x70 ; TMOD = 0x21 ; TL1 = 0x0fd ; TH1 = 0x0fd ; TR1 = 1 ; SCON = 0x50 ; ES = 1 ; ET0 = 1 ; EA = 1 ; temp1 = 0 ; WDI = ~ WDI ; } void delay(void) { int i,j; for (i=0 ;i<5;i++ ) for(j=0 ;i<120;j++) ; } void input(void) { intemp =P1&0x0f ; if(intemp==0x0f) { delay(); temp1=0x0f; } else { if ( input1==0 ) outputtemp1 = 0x010 ; if ( input1==0 ) outputtemp2 = 0x020 ; if ( input1==0 ) outputtemp3 = 0x040 ; if ( input1==0 ) outputtemp4 = 0x080 ; temp1 = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; } temp2 = temp1 & 0x0f0 ; P1= temp2 ; RI=0 ; TI=1 ; WDI = ~ WDI ; } void recieve(void) { ES=0 ; if(RI) ES=1 ; else temp2=SBUF; P1=temp2 ; ES=1 ; WDI = ~ WDI ; } void transport(void) { SBUF =temp2 ; if (TI) SBUF=temp2 ; else WDI = ~ WDI ; } void main(void) { initialcpu () ; while(1) { input() ; } } 5)編譯結果: 程序我編譯了,已經可以生成HEX文件。但是沒有開發(fā)板調試功能。 自學好累,希望各位熟悉串口程序的幫忙看看程序是否能夠實現(xiàn)功能。 |
| 2樓: | >>參與討論 |
| 作者: hotpower 于 2005/6/19 3:15:00 發(fā)布:
temp1=(P1 & 0x0f) ^ 0x0f;豈不更簡單??? 程序太亂...玩玩可以... |
|
| 3樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/20 9:03:00 發(fā)布:
加了標注 #include <AT89x51.h> ;包含的頭文件 sbit input1 = P1^0 ; ;開關量輸入定義 sbit input2 = P1^1 ; sbit input3 = P1^2 ; sbit input4 = P1^3 ; sbit WDI = P3^2 ; int i,j ; ;延時子程序中用到的變量定義 unsigned CHAR flag ; ;上次輸入結果標志 unsigned CHAR intemp,temp1,temp2,outputtemp1,outputtemp2,outputtemp3,outputtemp4 ; ;輸出結果中間變量 void initialcpu (void) ;上電時單片機初始化函數(shù) { SP = 0x70 ; ;堆棧保護 TMOD = 0x21 ; ;定義工作方式為方式2 TL1 = 0x0fd ; ;波特率9600 TH1 = 0x0fd ; TR1 = 1 ; ;啟動定時器1中斷,注意:此時中斷還沒開 SCON = 0x50 ; ; ES = 1 ; ;啟動串口中斷 ET0 = 1 ; ;啟動定時器中斷 EA = 1 ; ;啟動全部中斷 temp1 = 0 ; ;輸出標志清0 WDI = ~ WDI ; ;看門狗取反 } void delay(void) ;延時子程序 { int i,j; for (i=0 ;i<5;i++ ) for(j=0 ;i<120;j++) ; } void input(void) ;開關量輸入檢測程序 { intemp =P1&0x0f ; ;取P1口低四位 if(intemp==0x0f) ;判斷低四位是否都等于1,高電平無輸入 { delay(); ;消除抖動 temp1=0x0f; ;無輸出標志 } else ;否則檢測4個輸入管腳 { if ( input1==0 ) outputtemp1 = 0x010 ; if ( input1==0 ) outputtemp2 = 0x020 ; if ( input1==0 ) outputtemp3 = 0x040 ; if ( input1==0 ) outputtemp4 = 0x080 ; temp1 = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; ;把4個檢測結果保存為一個中間值 } temp2 = temp1 & 0x0f0 ; ;屏蔽4位開關量輸入 P1= temp2 ; ;把高四位送給P1口 RI=0 ; ;關閉串口接收 TI=1 ; ;軟件啟動串口發(fā)送 WDI = ~ WDI ; ;看門狗取反 } void recieve(void) ;串口接收服務子程序 { ES=0 ; ;關閉串口中斷 if(RI) ;判斷有無接收標志 ES=1 ; ;無接收標志,啟動串口標志 else ;有接收標志 temp2=SBUF; &nb |
|
| 4樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/20 9:11:00 發(fā)布:
to hotpower temp1=(P1 & 0x0f) ^ 0x0f;豈不更簡單??? 能否解釋清楚點。 這個程序是我的處女作,我現(xiàn)在正在門外頭,不知道怎么入門,很多東西不明白,希望有人指點一下C51。 |
|
| 5樓: | >>參與討論 |
| 作者: ilone 于 2005/6/20 18:38:00 發(fā)布:
看了一會 SP = 0x70 ; ;堆棧保護 在c51里面要這個干什么呢? 去看看別人的例子 |
|
| 6樓: | >>參與討論 |
| 作者: gbchang 于 2005/6/20 19:28:00 發(fā)布:
看到的問題... void input(void) ;開關量輸入檢測程序 { intemp =P1&0x0f ; ;取P1口低四位 if(intemp==0x0f) ;判斷低四位是否都等于1,高電平無輸入 { delay(); ;消除抖動 temp1=0x0f; ;無輸出標志 } else ;否則檢測4個輸入管腳 { if ( input1==0 ) outputtemp1 = 0x010 ; /*if ( input1==0 ) outputtemp1 = 0x01F ;*/ if ( input1==0 ) outputtemp2 = 0x020 ; /*if ( input2==0 ) outputtemp2 = 0x02F ;*/ if ( input1==0 ) outputtemp3 = 0x040 ; /*if ( input3==0 ) outputtemp3 = 0x04F ;*/ if ( input1==0 ) outputtemp4 = 0x080 ; /*if ( input4==0 ) outputtemp4 = 0x08F ;*/ temp1 = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; ;把4個檢測結果保存為一個中間值 } /*就是把低4位取反放到高4位,并且低4位置1: temp1=(intemp * 0x10) ^ 0x0ff */ temp2 = temp1 & 0x0f0 ; ;屏蔽4位開關量輸入 /*temp2 = temp1 ; ;為什么要屏蔽?I/O作輸入時,是要輸出1的!*/ P1= temp2 ; ;把高四位送給P1口 RI=0 ; ;關閉串口接收 TI=1 ; ;軟件啟動串口發(fā)送 WDI = ~ WDI ; ;看門狗取反 } |
|
| 7樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/20 20:03:00 發(fā)布:
溢出了 { if ( input1==0 ) outputtemp1 = 0x010 ; /*if ( input1==0 ) outputtemp1 = 0x01F ;*/ if ( input1==0 ) outputtemp2 = 0x020 ; /*if ( input2==0 ) outputtemp2 = 0x02F ;*/ if ( input1==0 ) outputtemp3 = 0x040 ; /*if ( input3==0 ) outputtemp3 = 0x04F ;*/ if ( input1==0 ) outputtemp4 = 0x080 ; /*if ( input4==0 ) outputtemp4 = 0x08F ;*/ temp1 = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; ;把4個檢測結果保存為一個中間值 } /*就是把低4位取反放到高4位,并且低4位置1: temp1=(intemp * 0x10) ^ 0x0ff */ 如果有開關量輸入的話,那結果不就溢出了。。。 我是把P1的低四位作為開關量輸入(平時是高電平,有輸入時候是低電平),高四位作為輸出標志位。 |
|
| 8樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/20 20:06:00 發(fā)布:
為什么不要SP = 0x70 ; 堆棧保護 SP = 0x70 ; ;堆棧保護 這個在C中為什么不需要呢,難道C編寫的程序用自動保護堆棧? |
|
| 9樓: | >>參與討論 |
| 作者: hotpower 于 2005/6/20 20:26:00 發(fā)布:
此程序最大錯誤就在于C語言操作SP void initialcpu (void) ;上電時單片機初始化函數(shù) { SP = 0x70 ; ;堆棧保護//最致命之處!!!! TMOD = 0x21 ; ;定義工作方式為方式2 TL1 = 0x0fd ; ;波特率9600 TH1 = 0x0fd ; TR1 = 1 ; ;啟動定時器1中斷,注意:此時中斷還沒開 SCON = 0x50 ; ; ES = 1 ; ;啟動串口中斷 ET0 = 1 ; ;啟動定時器中斷 EA = 1 ; ;啟動全部中斷 temp1 = 0 ; ;輸出標志清0 WDI = ~ WDI ; ;看門狗取反 } C語言在main()函數(shù)前已自動分配(計算)SP. 那么 void main(void) ;主函數(shù) {//SP已確定!!!!!!!!!!!!!!!!!!!!!!! initialcpu () ; ;單片機初始化 while(1)//initialcpu()函數(shù)能返回此處嗎???如果能真是天大的巧合!!! { input() ; ;一直檢測輸入 } } 看了半天,只感到一句是精華: TI=1 ; ;軟件啟動串口發(fā)送 |
|
| 10樓: | >>參與討論 |
| 作者: brekai 于 2005/6/20 21:03:00 發(fā)布:
好,可以 可以.強頂啊 |
|
| 11樓: | >>參與討論 |
| 作者: isoar 于 2005/6/20 22:04:00 發(fā)布:
這種帖子怎么也能有“酷”字?! //-------------------文件包含部分 ---------------------------------------------- #include <REG51.H> //----------------------------------------------------------------------------- //-------------------常數(shù)及編譯預處理------------------------------------------- #define FOSC 12000000ul //11059200ul #define BAUD 9600 #define SMODX 1 #define TH1_VAL (256 - (unsigned CHAR)(FOSC * (1<<SMODX) * 1.0 / 384 / BAUD)) #define TL1_VAL TH1_VAL //----------------------------------------------------------------------------- //-------------------變量定義-------------------------------------------------- unsigned CHAR ucUartData; //串口數(shù)據(jù) bit bUartSign; //收到數(shù)據(jù)標志 //----------------------------------------------------------------------------- //-------------------函數(shù)定義-------------------------------------------------- void intUart(void) interrupt 4 {//串口接收函數(shù)(中斷方式) ucUartData=SBUF; bUartSign=1; RI=0; } void vUartTransmit(unsigned CHAR ucOutput) {//串口發(fā)送函數(shù) ES=0; //Stop Receive Interrupt SBUF=ucOutput; while(!TI); TI=0; ES=1; //Restart Receive Interrupt } void main(void) {//主函數(shù) //串口初始化 TMOD=0x20; //T1 模式 2(波特率發(fā)生模式) if (SMODX)PCON|=0x80; //SMOD=1(根據(jù)預處理信息設置SMOD位) TH1=TH1_VAL; //波特率設定值由編譯預處理信息確定 TL1=TL1_VAL; SM0=0; //穿行口模式 SM1=1; TR1=1; //啟動 T1 REN=1; //接收允許 EA=1; //中斷允許 ES=1; //串口中斷允許 TI=0; //發(fā)送標志位初始化 bUartSign=0; //收到數(shù)據(jù)標志 //串口初始化結束 while(1) {//主循環(huán) if (bUartSign) { vUartTransmit(ucUartData); bUartSign=0; } }//主循環(huán)結束 } //----------------------------------------------------------------------------- * - 本貼最后修改時間:2005-6-20 23:43:36 修改者:isoar |
|
| 12樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/21 18:19:00 發(fā)布:
改用定時器T0定時檢測,, //-------------------文件包含部分 ---------------------------------------------- #include <REG51.H> //----------------------------------------------------------------------------- //-------------------常數(shù)及編譯預處理------------------------------------------- #define FOSC 12000000ul //11059200ul #define BAUD 9600 #define SMODX 1 #define TH1_VAL (256 - (unsigned CHAR)(FOSC * (1<<SMODX) * 1.0 / 384 / BAUD)) #define TL1_VAL TH1_VAL #define ucUartData ucOutput //----------------------------------------------------------------------------- //-------------------變量定義-------------------------------------------------- unsigned CHAR ucUartData; //串口數(shù)據(jù) unsigned CHAR intemp,outputtemp1,outputtemp2,outputtemp3,outputtemp4; bit bUartSign; //收到數(shù)據(jù)標志 sbit input1 = P1^0 ; sbit input2 = P1^1 ; sbit input3 = P1^2 ; sbit input4 = P1^3 ; sbit WDI = P3^2 ; //----------------------------------------------------------------------------- //-------------------函數(shù)定義-------------------------------------------------- void intUart(void) interrupt 4 {//串口接收函數(shù)(中斷方式) ucUartData=SBUF; P1=ucUartData; bUartSign=1; RI=0; WDI = ~ WDI ; } void vUartTransmit(unsigned CHAR ucOutput) {//串口發(fā)送函數(shù) ES=0; //Stop Receive Interrupt SBUF=ucOutput; while(!TI); TI=0; ES=1; //Restart Receive Interrupt } void t0(void) interrupt 1 using 0 { ET0 = 0 ; TR0 = 0 ; WDI = ~ WDI ; TH0 = 0xB1 ; //重新載入定時器T0時間常數(shù) TL0 = 0xE0; intemp = P1 & 0x0f ; if ( intemp==0x0f ) //沒有開關量輸入 { ucOutput = 0x0f ; P1=ucOutput; } else //有開關量輸入 { if ( input1==0 ) outputtemp1 = 0x01E ; if ( input1==0 ) outputtemp2 = 0x02D ; if ( input1==0 ) outputtemp3 = 0x04B ; if ( input1==0 ) outputtemp4 = 0x087 ; ucOutput = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; P1=ucOutput; } RI = 0 ; TI = 1 ; WDI = ~ WDI ; } void main(void) {//主函數(shù) //串口初始化 TMOD=0x21; //T1 模式 2(波特率發(fā)生模式) //if (SMODX)PCON|=0x80; //SMOD=1(根據(jù)預處理信息設置SMOD位) TH1=TH1_VAL; //波特率設定值由編譯預處理信息確定 TL1=TL1_VAL; TR1=1; //啟動 T1 SCON=0x50; //設置串行口工作方式 ES=1; //串口中斷允許 ET0=1; //啟動定時器T EA=1; //啟動全部中斷 TH0=0xB1 ; //載入T0定時常數(shù) TL0=0xE0; TR0=1; REN=1; //接收允許 TI=0;& |
|
| 13樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/21 18:24:00 發(fā)布:
詢問高手 我是自學的新手,請教一下: 第一個不懂 //-------------------常數(shù)及編譯預處理------------------------------------------- #define FOSC 12000000ul //11059200ul #define BAUD 9600 #define SMODX 1 #define TH1_VAL (256 - (unsigned CHAR)(FOSC * (1<<SMODX) * 1.0 / 384 / BAUD)) #define TL1_VAL TH1_VAL //----------------------------------------------------------------------------- 這部分是怎么應用的呢,有沒有什么參考書上有詳細介紹的。 第二個不懂: void intUart(void) interrupt 4 我看很多程序上都有用到類似這樣的函數(shù),這個是怎么看的呢。 怎么知道它是串口中斷函數(shù)還是定時中斷函數(shù),有沒有具體的定義。 如果把intUart改成其他的名字可以不。 * - 本貼最后修改時間:2005-6-21 18:33:16 修改者:baipengwei |
|
| 14樓: | >>參與討論 |
| 作者: isoar 于 2005/6/22 23:19:00 發(fā)布:
21ic可以問路,但路總得自己一步一步地走! 你的第一個不懂 //-------------------常數(shù)及編譯預處理------------------------------------------- #define FOSC 12000000ul //11059200ul #define BAUD 9600 #define SMODX 1 #define TH1_VAL (256 - (unsigned CHAR)(FOSC * (1<<SMODX) * 1.0 / 384 / BAUD)) #define TL1_VAL TH1_VAL //----------------------------------------------------------------------------- 上面的東西除了 "unsigned CHAR"這個數(shù)據(jù)類型,其它的都是標準c的內容,你可以去看譚浩強的《c程序設計》。至于那個表達式,只是書上的計算BAUD RATE 的公式。 第二個不懂: void intUart(void) interrupt 4 我看很多程序上都有用到類似這樣的函數(shù),這個是怎么看的呢。 怎么知道它是串口中斷函數(shù)還是定時中斷函數(shù),有沒有具體的定義。 如果把intUart改成其他的名字可以不。 如果你也看書了,不知道你是否仔細看了單片機的書?“interrupt 4”這個修飾符不是標準c的內容,既然它是中斷函數(shù),那么中斷向量肯定是由它來確定的,至于為什么,自己去單片機書里找吧?我個人感覺,你是學計算機的,或是僅僅是從c語言開始學單片機的。也許不學匯編也可以學好單片機,但我個人認為這是不可能的。所以你要是想學單片機,就一定要懂,單片機的結構和原理,至少了解它的匯編指令的工作過程。然后再去用c開發(fā)。 個人總結:做單片機項目用c很方便,可是你要想學會單片機學通單片機,一定是從匯編進入,否則做不出好的單片機程序。 |
|
| 15樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/23 21:10:00 發(fā)布:
用兩塊板子相連,控制不了 硬件資源: 1.兩個一樣的電路板, 2.電路板使用232通信。 實驗步驟: 1.我首先使用一塊電路板。 在原先同事的基礎上修改程序(匯編的),使程序達到如下程度: 1》計算機從電路板上收到的 1)當有開關量1輸入的時候,我的計算機上串口收到如下: S0000000000000001 2)當有開關量2輸入的時候,我的計算機上串口收到如下: S0000000000000010 3)當有開關量3輸入的時候,我的計算機上串口收到如下: S0000000000000100 4)當有開關量1輸入的時候,我的計算機上串口收到如下: S0000000000001000 2》計算機往電路板如下協(xié)議,對應的輸出。 1)發(fā)送 \x0aS0000000000000001\x0d ,電路板上繼電器1輸出。 2)發(fā)送 \x0aS0000000000000010\x0d ,電路板上繼電器2輸出。 3)發(fā)送 \x0aS0000000000000100\x0d ,電路板上繼電器3輸出。 4)發(fā)送 \x0aS0000000000001000\x0d ,電路板上繼電器4輸出。 (每個繼電器對應一個IO口) 2.不通過計算機的時候的實驗 我使用兩個開關電源分別給兩塊板子供電。中間的使用一個串口線把兩個板子的串口連在一起。 根據(jù)第一步驟的修改后的程序。 應該是我在板子1上有開關量輸入的時候,對應的板子2有繼電器輸出。是不是這樣? 1 現(xiàn)在的問題是,板子1開關量輸入的時候,板子2沒有反映、、 求問。。 |
|
| 16樓: | >>參與討論 |
| 作者: dengm 于 2005/6/23 21:32:00 發(fā)布:
re: RI=0 ; ;關閉串口接收 ============= A: RI=0 不是關閉串口接收, REN=0 才是關閉串口接收 |
|
| 17樓: | >>參與討論 |
| 作者: mgf006 于 2005/6/24 19:29:00 發(fā)布:
這幾句不應該要的 else { if ( input1==0 ) outputtemp1 = 0x010 ; if ( input1==0 ) outputtemp2 = 0x020 ; if ( input1==0 ) outputtemp3 = 0x040 ; if ( input1==0 ) outputtemp4 = 0x080 ; 這幾個是不是有點放屁脫褲子呀。。 |
|
| 18樓: | >>參與討論 |
| 作者: lufeijian 于 2005/6/25 8:41:00 發(fā)布:
串口有沒有這么麻煩? //UART中斷程序 void uart(void) { unsigned CHAR TEMP; if(RI) { TEMP=SBUF; RI=0; } else { TI=0; } P1=TEMP; } |
|
| 19樓: | >>參與討論 |
| 作者: baipengwei 于 2005/6/25 10:02:00 發(fā)布:
這個是接收單個字節(jié)的,那如果我需要設定協(xié)議,數(shù)據(jù)很多呢 //UART中斷程序 void uart(void) { unsigned CHAR TEMP; if(RI) { TEMP=SBUF; RI=0; } else { TI=0; } P1=TEMP; } 如果我要加上起始位,停止位,中間放數(shù)據(jù)的這種格式,數(shù)據(jù)量比較大的情況下呢。 如果用同一個程序,使用在兩個一樣的板子上,板子A檢測到有輸入,板子B就會有輸出;同道理當子B檢測到有輸入,板子A就會有輸出;兩個板子互相通過串口控制。這樣兩個板子在串口資源上是,不是會有沖突呀,在程序上要怎么實現(xiàn): |
|
| 20樓: | >>參與討論 |
| 作者: lufeijian 于 2005/6/25 12:46:00 發(fā)布:
這個要自己定協(xié)議才行 |
|
| 21樓: | >>參與討論 |
| 作者: hiberhe 于 2005/6/26 23:41:00 發(fā)布:
怎么都不用緩沖區(qū)的?可以參考“丁丁”那個程序 已經有中斷,為什么還要用T0查?為什么不使用發(fā)送和接收緩沖區(qū)呢?這樣方便很多 |
|
| 22樓: | >>參與討論 |
| 作者: 半月微微 于 2005/6/28 13:52:00 發(fā)布:
還在定義SP的值,暈倒.......... |
|
| 23樓: | >>參與討論 |
| 作者: lufeijian 于 2005/6/29 10:07:00 發(fā)布:
支持 |
|
| 24樓: | >>參與討論 |
| 作者: willisl 于 2005/7/12 9:56:00 發(fā)布:
挺好的就 |
|
| 25樓: | >>參與討論 |
| 作者: czy840620 于 2005/7/14 18:41:00 發(fā)布:
匯編語言 怎么都是用C編的啊?有沒有用匯編語言的。 |
|
| 26樓: | >>參與討論 |
| 作者: baipengwei 于 2005/7/18 22:13:00 發(fā)布:
有匯編的整個源程序 你搜索一下“一個小系統(tǒng)的構造,,89C2051的串口做主機發(fā)送數(shù)據(jù),從機接收數(shù)據(jù)的實驗” 把2051改用89C51也是同樣可以實現(xiàn),只是比較浪費資源。 |
|
| 27樓: | >>參與討論 |
| 作者: zhql198 于 2005/7/22 21:53:00 發(fā)布:
編譯了一下,怎么不行啊 程序我編譯了,已經可以生成HEX文件 我編譯了一下,怎么不行啊 |
|
| 28樓: | >>參與討論 |
| 作者: 違章 于 2005/7/31 14:39:00 發(fā)布:
我也是編譯過不了 |
|
| 29樓: | >>參與討論 |
| 作者: cp8848 于 2005/8/11 19:49:00 發(fā)布:
11 |
|
| 30樓: | >>參與討論 |
| 作者: tao_xu99 于 2005/8/15 8:10:00 發(fā)布:
能努力學習就應該提倡 能努力學習就應該提倡 |
|
| 31樓: | >>參與討論 |
| 作者: hongguolin 于 2005/8/24 17:37:00 發(fā)布:
支持 |
|
| 32樓: | >>參與討論 |
| 作者: tao_xu99 于 2005/8/29 7:28:00 發(fā)布:
這就是C51與匯編的區(qū)別啊? 勤學多問有好處 |
|
| 33樓: | >>參與討論 |
| 作者: z41992929 于 2005/8/29 14:38:00 發(fā)布:
串口其實也可以全雙工的 如果我要加上起始位,停止位,中間放數(shù)據(jù)的這種格式,數(shù)據(jù)量比較大的情況下呢 目前單片機里串口就只有8位和9位兩種,如果你定義的格式中的數(shù)據(jù)超過了9位,那么就不能用串口來傳送,必須用軟件去模擬。具體怎么模擬,看看書和別人的程序 如果用同一個程序,使用在兩個一樣的板子上,板子A檢測到有輸入,板子B就會有輸出;同道理當子B檢測到有輸入,板子A就會有輸出;兩個板子互相通過串口控制。這樣兩個板子在串口資源上是,不是會有沖突呀,在程序上要怎么實現(xiàn): 單片機里的串口其實就是一根傳輸線和一根接受線,有內部電路通過檢測線上的電平來確定線上是否有數(shù)據(jù),所以是兩根線獨立工作的,也就是平時所謂的全雙工,對于是否有沖突的問題,其實你不用擔心,單片機里有發(fā)送緩沖器和接受緩沖器,雖然它們地址一樣,但并不是同一存儲區(qū),單片機在執(zhí)行指令時會根據(jù)指令有選擇的讀取,不會寫接受緩沖器,也不會讀接受緩沖器,但從地址上是無法區(qū)分的 |
|
| 34樓: | >>參與討論 |
| 作者: z41992929 于 2005/8/29 14:49:00 發(fā)布:
串口也可以全雙工的啊 如果我要加上起始位,停止位,中間放數(shù)據(jù)的這種格式,數(shù)據(jù)量比較大的情況下呢。 單片機串口只有8位和9位兩種,9位是有一位是檢驗位,而且單片機在處理時,會自動加上起始位和停止位,這些都是有硬件來完成,程序中根本不用管,如果你想傳更多的數(shù)據(jù),就不能用串口,必須軟件來模擬。 如果用同一個程序,使用在兩個一樣的板子上,板子A檢測到有輸入,板子B就會有輸出;同道理當子B檢測到有輸入,板子A就會有輸出;兩個板子互相通過串口控制。這樣兩個板子在串口資源上是,不是會有沖突呀,在程序上要怎么實現(xiàn): 單片機上的串口對應有兩個緩沖器:接受和發(fā)送,雖然地址一樣,但是在讀寫是對應著不同的地址空間,讀的肯定是接受緩沖器,寫的一定是發(fā)送緩沖器,它們之間的選擇是有指令系統(tǒng)來確定的,完全不會沖突,要不然怎么會是全雙工列?。 |
|
| 35樓: | >>參與討論 |
| 作者: z41992929 于 2005/8/29 15:10:00 發(fā)布:
串口可以全雙工的! 單片機里的串口數(shù)據(jù)的起始位和停止位是由硬件來完成的,在程序中不必去管這么多,管好自己的數(shù)據(jù)就行了,象你要發(fā)送大量的數(shù)據(jù),可以提高波特率,或者軟件來模擬收發(fā),其中數(shù)據(jù)位是幾位,就看你的喜好了,單片機數(shù)據(jù)位最大只有9位。 另外,單片機對于串口資源的分配,有兩個獨立的緩沖器,一個作為發(fā)送,一個作為接受,雖然地址一樣,但是單片機自己會去區(qū)分,寫好程序就好了,為什么說串口是全雙工的,也就是由于這個原因。 |
|
| 36樓: | >>參與討論 |
| 作者: 陳雙君 于 2005/8/29 22:00:00 發(fā)布:
大家來看一看。 1)IO分配: P1.0——P1.3 :開關量低電平輸入; P1.4——P1.7 :開關量有輸入標志; P3.2 : 691看門狗輸入 2)功能描述: 兩個同樣的板子,當其中有一個板子,開關量有輸入時候,兩塊板子上的開關量有輸入標志都動作。利用串口進行傳送。 3)電路圖: 很簡單,自己想象都可以想得出來。 4)源程序: #include <AT89x51.h> sbit input1 = P1^0 ; sbit input2 = P1^1 ; sbit input3 = P1^2 ; sbit input4 = P1^3 ; sbit WDI = P3^2 ; int i,j ; unsigned CHAR flag ; unsigned CHAR intemp,temp1,temp2,outputtemp1,outputtemp2,outputtemp3,outputtemp4 ; void initialcpu (void) { SP = 0x70 ; TMOD = 0x21 ; TL1 = 0x0fd ; TH1 = 0x0fd ; TR1 = 1 ; SCON = 0x50 ; ES = 1 ; ET0 = 1 ; EA = 1 ; temp1 = 0 ; WDI = ~ WDI ; } void delay(void) { int i,j; for (i=0 ;i<5;i++ ) for(j=0 ;i<120;j++) ; } void input(void) { intemp =P1&0x0f ; if(intemp==0x0f) { delay(); temp1=0x0f; } else { if ( input1==0 ) outputtemp1 = 0x010 ; if ( input1==0 ) outputtemp2 = 0x020 ; if ( input1==0 ) outputtemp3 = 0x040 ; if ( input1==0 ) outputtemp4 = 0x080 ; temp1 = outputtemp1 + outputtemp2 + outputtemp3 +outputtemp4 ; } temp2 = temp1 & 0x0f0 ; P1= temp2 ; RI=0 ; TI=1 ; WDI = ~ WDI ; } void recieve(void) { ES=0 ; if(RI) ES=1 ; else temp2=SBUF; P1=temp2 ; ES=1 ; WDI = ~ WDI ; } void transport(void) { SBUF =temp2 ; if (TI) SBUF=temp2 ; else WDI = ~ WDI ; } void main(void) { initialcpu () ; while(1) { input() ; } } 5)編譯結果: 程序我編譯了,已經可以生成HEX文件。但是沒有開發(fā)板調試功能。 自學好累,希望各位熟悉串口程序的幫忙看看程序是否能夠實現(xiàn)功能。 |
|
| 37樓: | >>參與討論 |
| 作者: asdluo 于 2005/9/7 15:42:00 發(fā)布:
看著暈 好象不用這樣多吧?看著暈 不過樓主自己能寫出程序就比我強了 |
|
| 38樓: | >>參與討論 |
| 作者: bcf9088 于 2005/9/13 8:09:00 發(fā)布:
hui 望繼續(xù)努力 |
|
| 39樓: | >>參與討論 |
| 作者: dandangl 于 2005/9/13 12:23:00 發(fā)布:
cool |
|
| 40樓: | >>參與討論 |
| 作者: icecut 于 2005/9/13 12:55:00 發(fā)布:
不應該有酷 第一個程序占用太多資源!不可取。應該用第二個程序! 最后說串口簡單的哪個哥們,你是不是用PHILIP的?定時器是要設置的。 |
|
| 41樓: | >>參與討論 |
| 作者: qzhzh607 于 2005/9/18 13:06:00 發(fā)布:
恢復 |
|
| 42樓: | >>參與討論 |
| 作者: qzhzh607 于 2005/9/18 13:09:00 發(fā)布:
串口調試助手源程序 作者:龔建偉 2001.8.25 可以任意轉載,但必須注明作者和說明來自http://roaringwind.best.163.com,不得作為商用 1.建立項目 2.在項目中插入MSComm控件 3.利用ClassWizard定義CMSComm類控制變量 4.在對話框中添加控件 5.添加串口事件消息處理函數(shù)OnComm() 6.打開和設置串口參數(shù) 7.發(fā)送數(shù)據(jù) 8.發(fā)送十六進制字符 9.在接收框中以十六進制顯示 10.如何設置自動發(fā)送 11.什么是VARIANT數(shù)據(jù)類型?如何使用VARIANT數(shù)據(jù)類型? 這是串口調試助手源程序及編程詳細過程(一)的續(xù)篇,首先謝謝朋友們的支持與鼓勵。 這是更新后適合本文的源程序(2001.8.25制作),如果還沒有下載源程序,又對本文有興趣,請 立即下載 (當然,你看完本文也可以自己做出來,這個程序是接著上一個做的,如果你沒下載前面程序,則沒必要再下載了,本程序全部包含)。 8.發(fā)送十六進制字符 在主對話框中加入一個復選接鈕,ID為IDC_CHECK_HEXSEND Caption: 十六進制發(fā)送,再利用ClassWizard為其添加控制變量:m_ctrlHexSend; 在ClassView中為SCommTestDlg類添加以下兩個PUBLIC成員函數(shù),并輸入相應代碼; //由于這個轉換函數(shù)的格式限制,在發(fā)送框中的十六制字符應該每兩個字符之間插入一個空隔 //如:A1 23 45 0B 00 29 //CByteArray是一個動態(tài)字節(jié)數(shù)組,可參看MSDN幫助 int CSCommTestDlg::String2Hex(CString str, CByteArray &senddata) { int hexdata,lowhexdata; int hexdatalen=0; int len=str.GetLength(); senddata.SetSize(len/2); for(int i=0;i<len;) { CHAR lstr,hstr=str[i]; if(hstr==' ') { i++; continue; } i++; if(i>=len) break; lstr=str[i]; hexdata=ConvertHexChar(hstr); lowhexdata=ConvertHexChar(lstr); if((hexdata==16)||(lowhexdata==16)) break; else hexdata=hexdata*16+lowhexdata; i++; senddata[hexdatalen]=(CHAR)hexdata; hexdatalen++; } senddata.SetSize(hexdatalen); return hexdatalen; } //這是一個將字符轉換為相應的十六進制值的函數(shù) //好多C語言書上都可以找到 //功能:若是在0-F之間的字符,則轉換為相應的十六進制字符,否則返回-1 CHAR CSCommTestDlg::ConvertHexChar(CHAR ch) { if((ch>='0')&&(ch<='9')) return ch-0x30; else if((ch>='A')&&(ch<='F')) return ch-'A'+10; else if((ch>='a')&&(ch<='f')) return ch-'a'+10; else return (-1); } 再將CSCommTestDlg::OnButtonManualsend()修改成以下形式: void CSCommTestDlg::OnButtonManualsend() { // TODO: Add your CONTROL notification handler code here UpdateData(TRUE); //讀取編輯框內容 if(m_ctrlHexSend.GetCheck()) { CByteArray hexdata; int len=String2Hex(m_strTXData,hexdata); //此處返回的len可以用于計算發(fā)送了多少個十六進制數(shù) m_ctrlComm.SetOutput(COleVariant(hexdata)); //發(fā)送十六進制數(shù)據(jù) } else m_ctrlComm.SetOutput(COleVariant(m_strTXData));//發(fā)送ASCII字符數(shù)據(jù) } 現(xiàn)在,你先將串口線接好并打開串口調試助手V2.1,選上以十六制顯示,設置好相應串口,然后運行我們這個程序,在發(fā)送框中輸入00 01 02 03 A1 CC等十六進制字符,并選上以十六進制發(fā)送,單擊手動發(fā)送,在串口調試助手的接收框中應該可以看到00 01 02 03 A1 CC了。 9.在接收框中以十六進制顯示 這就容易多了: 在主對話框中加入一個復選接鈕,IDC_CHECK_HEXDISPLAY Caption: 十六進制顯示,再利用ClassWizard為其添加控制變量:m_ctrlHexDiaplay。 然后修改CSCommTestDlg::OnComm()函數(shù): void CSCommTestDlg::OnComm() { // TODO: Add your CONTROL notification handler code here VARIANT variant_inp; COleSafeArray safearray_inp; LONG len,k; BYTE rxdata[2048]; //設置BYTE數(shù)組 An 8-bit integerthat is not signed. CString strtemp; if(m_ctrlComm.GetCommEvent()==2) //事件值為2表示接收緩沖區(qū)內有字符 { variant_inp=m_ctrlComm.GetInput(); //讀緩沖區(qū) safearray_inp=variant_inp; //VARIANT型變量轉換為ColeSafeArray型變量 len=safearray_inp.GetOneDimSize(); //得到有效數(shù)據(jù)長度 for(k=0;k<len;k++) safearray_inp.GetElement(&k,rxdata+k);//轉換為BYTE型數(shù)組 for(k=0;k<len;k++) //將數(shù)組轉換為Cstring型變量 { BYTE bt=*(CHAR*)(rxdata+k); //字符型 if(m_ctrlHexDisplay.GetCheck()) strtemp.Format("%02X ",bt); //將字符以十六進制方式送入臨時變量strtemp存放,注意這里加入一個空隔 else strtemp.Format("%c",bt); //將字符送入臨時變量strtemp存放 m_strRXData+=strtemp; //加入接收編輯框對應字符串 } } UpdateData(FALSE); //更新編輯框內容 } 測試:在串口調試助手發(fā)送框中輸入00 01 02 03 A1 CC等十六進制字符,并選上以十六進制發(fā)送,單擊手動發(fā)送,在本程序運行后選上以十六進制顯示,在串口調試助手中單擊手動發(fā)送或自動發(fā)送,則在本程序的接收框中應該可以看到00 01 02 03 A1 CC了。 10.如何設置自動發(fā)送 最簡單的設定自動發(fā)送周期是用SetTimer()函數(shù),這在數(shù)據(jù)采集中很有用,在控制中指令的傳送也可能用到定時發(fā)送。 方法是:在ClassWizard中選上MessageMap卡,然后在Objects IDs選中CSCommTestDlg類,再在Messages框中選上WM_TIMER消息,單擊ADD_FUNCTION加入void CSCommTestDlg::OnTimer(UINT nIDEvent) 函數(shù),這個函數(shù)是放入“時間到”后要處理的代碼: void CSCommTestDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default OnButtonManualsend(); CDialog::OnTimer(nIDEvent); } 再在在主對話框中加入一個復選接鈕,ID為IDC_CHECK_AUTOSEND Caption: 自動發(fā)送(周期1秒),再利用ClassWizard為其添加BN_CLICK消息處理函數(shù)void CSCommTestDlg::OnCheckAutosend(): void CSCommTestDlg::OnCheckAutosend() { // TODO: Add your CONTROL notification handler code here m_bAutoSend=!m_bAutoSend; if(m_bAutoSend) { SetTimer(1,1000,NULL);//時間為1000毫秒 } else { KillTimer(1); //取消定時 } } 其中:m_bAutoSend為BOOL型變量,在CLASSVIEW中為CSCommTestDlg類加入,并在構造函數(shù)中初始化: m_bAutoSen=FALSE; 現(xiàn)在可以運行程序測試了。 11.什么是VARIANT數(shù)據(jù)類型?如何使用VARIANT數(shù)據(jù)類型? 不知如何使用VARIANT數(shù)據(jù)類型, 有不少朋友對VARIANT這個新的數(shù)據(jù)類型大感頭疼。SetOutput()函數(shù)中 需要的VARIANT參數(shù)還可以使用COleVariant類的構造函數(shù)簡單生成,現(xiàn)在GetInput()函數(shù)的返回值也成了VARIANT類型,那么如何從返回的值中提取有用的內容。 VARIANT及由之而派生出的COleVariant類主要用于在OLE自動化中傳遞數(shù)據(jù)。實際上VARIANT也只不過是一個新定義的結構罷了,它的主要成員包括一個聯(lián)合體及一個變量。該聯(lián)合體由各種類型的數(shù)據(jù)成員構成, 而該變量則用來指明聯(lián)合體中目前起作用的數(shù)據(jù)類型。我們所關心的接收到的數(shù)據(jù)就存儲在該聯(lián)合體的某個數(shù)據(jù)成員中。 該聯(lián)合體中包含的數(shù)據(jù)類型很多,從一些簡單的變量到非常復雜的數(shù)組和指針。由于通過串口接收到的內容常常是一個字節(jié)串,我們將使用其中的某個數(shù)組或指針來訪問接收到的數(shù)據(jù)。這里推薦給大家的是指向一個SAFEARRAY(COleSafeArray)類型變量。新的數(shù)據(jù)類型SAFEARRAY正如其名字一樣,是一個“安全數(shù)組”,它能根據(jù)系統(tǒng)環(huán)境自動調整其16位或32 位的定義,并且不會被OLE改變(某些類型如BSTR在16位或32位應用程序間傳遞時會被OLE翻譯從而破壞其中的二進制數(shù)據(jù))。大家無須了解SAFEARRAY的具體定義,只要知道它是另外一個結構,其中包含一個 (void *)類型的指針pvData,其指向的內存就是存放有用數(shù)據(jù)的地方。 簡而言之,從GetInput()函數(shù)返回的VARIANT類型變量中,找出parray 指針,再從該指針指向的SAFEARRAY變量中找出pvData指針,就可以向訪問數(shù)組一樣取得所接收到的數(shù)據(jù)了。具體應用請參見void CSCommTestDlg::OnComm()函數(shù)。 大概我現(xiàn)在也說不清這個問題,我自己從第一次接觸這個東西,到現(xiàn)在還是給別人講不清。 另:二進制收發(fā)設置請參考MSComm控件說明 |
|
| 43樓: | >>參與討論 |
| 作者: woaimiaoqu 于 2005/9/19 18:21:00 發(fā)布:
有些囉唆 |
|
| 44樓: | >>參與討論 |
| 作者: liy123 于 2005/10/4 10:36:00 發(fā)布:
還是匯編好 用匯編省事的多. |
|
| 45樓: | >>參與討論 |
| 作者: yang8901 于 2005/10/10 8:18:00 發(fā)布:
ok |
|
| 46樓: | >>參與討論 |
| 作者: helloCAN 于 2005/10/18 14:41:00 發(fā)布:
關于USB-CAN2的問題 各位大蝦: 請問誰用過周立功公司的USB-CAN2只能接口卡,我在使用過程中有些問題請教, 我在復位模式下或工作模式下讀命令寄存器CMR怎仫總是00,可書上明明說該寄存器只寫的,讀出得數(shù)為ff,另請問該接口卡能接收CAn數(shù)據(jù)嗎? 請問有無 哈爾濱 的CAN高手,急需請教關于CAN的一些問題,謝謝! 請聯(lián)系 0451-82511045 王元偉 |
|
| 47樓: | >>參與討論 |
| 作者: linuxgirl 于 2005/10/21 8:44:00 發(fā)布:
還好 我做的項目如果是用串口就簡單多了 |
|
| 48樓: | >>參與討論 |
| 作者: pchaofei 于 2005/10/22 9:48:00 發(fā)布:
interrupt 4 回去看看interrupt 4是指向哪里的 |
|
| 49樓: | >>參與討論 |
| 作者: lzl869 于 2005/10/28 8:37:00 發(fā)布:
不錯的程序 硬件電路可以用最通用的那種吧? |
|
| 50樓: | >>參與討論 |
| 作者: 陳雙君 于 2005/10/30 21:36:00 發(fā)布:
這樣子不行的, 你在暫存器里頭放了解什么呀. 你的那個協(xié)儀呢? 你上下位機通信不用上下位機協(xié)儀的么?還是你有協(xié)儀但不拿出來給我們看呀 |
|
| 51樓: | >>參與討論 |
| 作者: 陳雙君 于 2005/11/2 17:03:00 發(fā)布:
我沒有用過你這樣的。 你這樣寫起來我搞不懂能不能用, 我想問題不會很大的吧。 |
|
| 52樓: | >>參與討論 |
| 作者: lxl9726 于 2005/11/7 15:41:00 發(fā)布:
改一下! if(RI) 我認為應該改為 IF(!RI) |
|
| 53樓: | >>參與討論 |
| 作者: hanghang 于 2005/11/24 13:20:00 發(fā)布:
很好呀 |
|
| 54樓: | >>參與討論 |
| 作者: northerns 于 2005/12/13 9:58:00 發(fā)布:
hao |
|
| 55樓: | >>參與討論 |
| 作者: 旋風羊 于 2006/2/6 22:39:00 發(fā)布:
好東西 |
|
| 56樓: | >>參與討論 |
| 作者: zt_bj 于 2006/2/13 0:39:00 發(fā)布:
Thank you. |
|
| 57樓: | >>參與討論 |
| 作者: baipengwei 于 2006/5/8 10:56:00 發(fā)布:
1年后的程序-串口自發(fā)自收程序 /****************************************************************************/ /* */ /* COPYRIGHT (c) 2005, 老樹工作室 */ /* All rights reserved. */ /* */ /* http://www.saintone.net */ /****************************************************************************/ /****************************************************************************/ /* 文件名:comint.c */ /* 版 本:Version 1.0 */ /* 描 述:在開發(fā)板上實現(xiàn),串口數(shù)據(jù)自發(fā)自收 */ /* 協(xié)議頭:\x0a */ /* 數(shù)據(jù):data1,data2,data3,data4,data5; */ /* 協(xié)議尾:\x0d */ /* */ /* 作 者:baipengwei */ /* */ /* 歷史記錄: */ /* 白鵬偉 2006-05-08 Creat Inital version. (Version 1.0) */ /****************************************************************************/ #include <reg52.h> #include <absacc.h> #include <intrins.h> #include <string.h> #define MAX_RINTL 16 /* 串口接收緩沖區(qū)長度 */ typedef unsigned CHAR u_CHAR; typedef unsigned int u_int; u_CHAR sy_index; /*串口數(shù)據(jù)索引 */ u_int e_index; /*協(xié)議控制碼索引 */ u_CHAR idata pint_buf[MAX_RINTL]; /* 串口接收緩沖區(qū) */ u_CHAR data pint_read; /* 串口緩沖區(qū)讀指針 */ u_CHAR data pint_write; /* 串口緩沖區(qū)寫指針 */ u_CHAR data psend_int; /* 串口發(fā)送允許標志 */ u_CHAR data data1,data2,data3,data4,data5; /*串口收到的有效數(shù)據(jù)*/ bit comfig; /*串口收到完整數(shù)據(jù)串后標志位*/ /* 串口中斷服務程序,使用第3組寄存器 */ void com_int_proc(void) interrupt 4 using 1 { &nb |
|
| 58樓: | >>參與討論 |
| 作者: baipengwei 于 2006/5/8 11:05:00 發(fā)布:
以上程序已經在“南方的老樹"學習板驗證過 以上程序已經在“南方的老樹"學習板驗證過,把它粘出來,希望給跟我當初一樣的初學者一點幫助。 |
|
|
|
| 免費注冊為維庫電子開發(fā)網會員,參與電子工程師社區(qū)討論,點此進入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號 |