音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

登錄 免費注冊 首頁 | 行業(yè)黑名單 | 幫助
維庫電子市場網
技術交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術 | 電源技術 | 測控之家 | EMC技術 | ARM技術 | EDA技術 | PCB技術 | 嵌入式系統(tǒng)
驅動編程 | 集成電路 | 器件替換 | 模擬技術 | 新手園地 | 單 片 機 | DSP技術 | MCU技術 | IC 設計 | IC 產業(yè) | CAN-bus/DeviceNe

一個利用串口自發(fā)自收的完整的C源程序

作者:baipengwei 欄目:單片機
一個利用串口自發(fā)自收的完整的C源程序
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
temp1=(P1 & 0x0f) ^ 0x0f;豈不更簡單???
程序太亂...玩玩可以...

3樓: >>參與討論
baipengwei
加了標注
#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
to  hotpower
temp1=(P1 & 0x0f) ^ 0x0f;豈不更簡單???

能否解釋清楚點。

這個程序是我的處女作,我現(xiàn)在正在門外頭,不知道怎么入門,很多東西不明白,希望有人指點一下C51。

5樓: >>參與討論
ilone
看了一會
SP     = 0x70    ;               ;堆棧保護   
在c51里面要這個干什么呢?
去看看別人的例子

6樓: >>參與討論
gbchang
看到的問題...
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
溢出了
{
        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
為什么不要SP = 0x70 ; 堆棧保護
SP     = 0x70    ;               ;堆棧保護   

這個在C中為什么不需要呢,難道C編寫的程序用自動保護堆棧?

9樓: >>參與討論
hotpower
此程序最大錯誤就在于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
好,可以
可以.強頂啊

11樓: >>參與討論
isoar
這種帖子怎么也能有“酷”字?!
//-------------------文件包含部分 ----------------------------------------------
#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
改用定時器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
詢問高手
我是自學的新手,請教一下:

第一個不懂
//-------------------常數(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
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
用兩塊板子相連,控制不了
硬件資源:
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
re:
RI=0    ;                 ;關閉串口接收
=============
A:
  RI=0 不是關閉串口接收, REN=0 才是關閉串口接收

17樓: >>參與討論
mgf006
這幾句不應該要的
else
        {            
        if ( input1==0 ) outputtemp1 = 0x010 ;
        if ( input1==0 ) outputtemp2 = 0x020 ;
        if ( input1==0 ) outputtemp3 = 0x040 ;
        if ( input1==0 ) outputtemp4 = 0x080 ;


這幾個是不是有點放屁脫褲子呀。。

18樓: >>參與討論
lufeijian
串口有沒有這么麻煩?
//UART中斷程序
void uart(void)
{
    unsigned CHAR TEMP;
    if(RI)
    {
     TEMP=SBUF;
     RI=0;
     }
    else
    {
     TI=0;
    }
    P1=TEMP;
}

19樓: >>參與討論
baipengwei
這個是接收單個字節(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
這個要自己定協(xié)議才行
 
21樓: >>參與討論
hiberhe
怎么都不用緩沖區(qū)的?可以參考“丁丁”那個程序
已經有中斷,為什么還要用T0查?為什么不使用發(fā)送和接收緩沖區(qū)呢?這樣方便很多

22樓: >>參與討論
半月微微
還在定義SP的值,暈倒..........
 
23樓: >>參與討論
lufeijian
支持
 
24樓: >>參與討論
willisl
挺好的就
 
25樓: >>參與討論
czy840620
匯編語言
怎么都是用C編的啊?有沒有用匯編語言的。

26樓: >>參與討論
baipengwei
有匯編的整個源程序
你搜索一下“一個小系統(tǒng)的構造,,89C2051的串口做主機發(fā)送數(shù)據(jù),從機接收數(shù)據(jù)的實驗”

把2051改用89C51也是同樣可以實現(xiàn),只是比較浪費資源。



27樓: >>參與討論
zhql198
編譯了一下,怎么不行啊
程序我編譯了,已經可以生成HEX文件
我編譯了一下,怎么不行啊

28樓: >>參與討論
違章
我也是編譯過不了
 
29樓: >>參與討論
cp8848
11
 
30樓: >>參與討論
tao_xu99
能努力學習就應該提倡
能努力學習就應該提倡

31樓: >>參與討論
hongguolin
支持
 
32樓: >>參與討論
tao_xu99
這就是C51與匯編的區(qū)別啊?
勤學多問有好處

33樓: >>參與討論
z41992929
串口其實也可以全雙工的
 
如果我要加上起始位,停止位,中間放數(shù)據(jù)的這種格式,數(shù)據(jù)量比較大的情況下呢

目前單片機里串口就只有8位和9位兩種,如果你定義的格式中的數(shù)據(jù)超過了9位,那么就不能用串口來傳送,必須用軟件去模擬。具體怎么模擬,看看書和別人的程序




如果用同一個程序,使用在兩個一樣的板子上,板子A檢測到有輸入,板子B就會有輸出;同道理當子B檢測到有輸入,板子A就會有輸出;兩個板子互相通過串口控制。這樣兩個板子在串口資源上是,不是會有沖突呀,在程序上要怎么實現(xiàn):

  單片機里的串口其實就是一根傳輸線和一根接受線,有內部電路通過檢測線上的電平來確定線上是否有數(shù)據(jù),所以是兩根線獨立工作的,也就是平時所謂的全雙工,對于是否有沖突的問題,其實你不用擔心,單片機里有發(fā)送緩沖器和接受緩沖器,雖然它們地址一樣,但并不是同一存儲區(qū),單片機在執(zhí)行指令時會根據(jù)指令有選擇的讀取,不會寫接受緩沖器,也不會讀接受緩沖器,但從地址上是無法區(qū)分的

34樓: >>參與討論
z41992929
串口也可以全雙工的啊
 
如果我要加上起始位,停止位,中間放數(shù)據(jù)的這種格式,數(shù)據(jù)量比較大的情況下呢。

單片機串口只有8位和9位兩種,9位是有一位是檢驗位,而且單片機在處理時,會自動加上起始位和停止位,這些都是有硬件來完成,程序中根本不用管,如果你想傳更多的數(shù)據(jù),就不能用串口,必須軟件來模擬。

如果用同一個程序,使用在兩個一樣的板子上,板子A檢測到有輸入,板子B就會有輸出;同道理當子B檢測到有輸入,板子A就會有輸出;兩個板子互相通過串口控制。這樣兩個板子在串口資源上是,不是會有沖突呀,在程序上要怎么實現(xiàn):

單片機上的串口對應有兩個緩沖器:接受和發(fā)送,雖然地址一樣,但是在讀寫是對應著不同的地址空間,讀的肯定是接受緩沖器,寫的一定是發(fā)送緩沖器,它們之間的選擇是有指令系統(tǒng)來確定的,完全不會沖突,要不然怎么會是全雙工列?。

35樓: >>參與討論
z41992929
串口可以全雙工的!

單片機里的串口數(shù)據(jù)的起始位和停止位是由硬件來完成的,在程序中不必去管這么多,管好自己的數(shù)據(jù)就行了,象你要發(fā)送大量的數(shù)據(jù),可以提高波特率,或者軟件來模擬收發(fā),其中數(shù)據(jù)位是幾位,就看你的喜好了,單片機數(shù)據(jù)位最大只有9位。 另外,單片機對于串口資源的分配,有兩個獨立的緩沖器,一個作為發(fā)送,一個作為接受,雖然地址一樣,但是單片機自己會去區(qū)分,寫好程序就好了,為什么說串口是全雙工的,也就是由于這個原因。

36樓: >>參與討論
陳雙君
大家來看一看。
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
看著暈
好象不用這樣多吧?看著暈
不過樓主自己能寫出程序就比我強了

38樓: >>參與討論
bcf9088
hui
望繼續(xù)努力

39樓: >>參與討論
dandangl
cool
 
40樓: >>參與討論
icecut
不應該有酷
第一個程序占用太多資源!不可取。應該用第二個程序!
最后說串口簡單的哪個哥們,你是不是用PHILIP的?定時器是要設置的。

41樓: >>參與討論
qzhzh607
恢復
 
42樓: >>參與討論
qzhzh607
串口調試助手源程序
作者:龔建偉  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
有些囉唆
 
44樓: >>參與討論
liy123
還是匯編好
用匯編省事的多.

45樓: >>參與討論
yang8901
ok
 
46樓: >>參與討論
helloCAN
關于USB-CAN2的問題
各位大蝦:
   請問誰用過周立功公司的USB-CAN2只能接口卡,我在使用過程中有些問題請教,
我在復位模式下或工作模式下讀命令寄存器CMR怎仫總是00,可書上明明說該寄存器只寫的,讀出得數(shù)為ff,另請問該接口卡能接收CAn數(shù)據(jù)嗎?
   請問有無 哈爾濱 的CAN高手,急需請教關于CAN的一些問題,謝謝!
   請聯(lián)系     0451-82511045
   王元偉



47樓: >>參與討論
linuxgirl
還好
我做的項目如果是用串口就簡單多了

48樓: >>參與討論
pchaofei
interrupt 4
回去看看interrupt 4是指向哪里的

49樓: >>參與討論
lzl869
不錯的程序
硬件電路可以用最通用的那種吧?

50樓: >>參與討論
陳雙君
這樣子不行的,
你在暫存器里頭放了解什么呀.
你的那個協(xié)儀呢?
你上下位機通信不用上下位機協(xié)儀的么?還是你有協(xié)儀但不拿出來給我們看呀


51樓: >>參與討論
陳雙君
我沒有用過你這樣的。
你這樣寫起來我搞不懂能不能用,
我想問題不會很大的吧。

52樓: >>參與討論
lxl9726
改一下!
if(RI)
我認為應該改為
IF(!RI)

53樓: >>參與討論
hanghang
很好呀
 
54樓: >>參與討論
northerns
hao
 
55樓: >>參與討論
旋風羊
好東西
 
56樓: >>參與討論
zt_bj
Thank you.
 
57樓: >>參與討論
baipengwei
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
以上程序已經在“南方的老樹"學習板驗證過
以上程序已經在“南方的老樹"學習板驗證過,把它粘出來,希望給跟我當初一樣的初學者一點幫助。

參與討論
昵稱:
討論內容:
 
 
相關帖子
那位兄弟做過熱能表或者暖氣表,請教請教!
風傳了好多年89C5X停產,但好像沒有
找一元左右的單片機
暈菜,又發(fā)現(xiàn)keil一個小bug  剛調試發(fā)現(xiàn)的
那位大大告訴我那款MPU有帶A/D,PWM功能,價格多少?
免費注冊為維庫電子開發(fā)網會員,參與電子工程師社區(qū)討論,點此進入


Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號