日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

STC延時(shí)會(huì)影響串口中斷收發(fā)??|我愛單片機(jī)

 quasiceo 2016-01-11
各位,我在寫一個(gè)串口通信的程序,代碼寫的比較長之后,發(fā)現(xiàn)串口收發(fā)變的不正常了
開始表現(xiàn)為,發(fā)指令后,接收數(shù)據(jù)延后,接著寫功能代碼,到最后發(fā)現(xiàn),發(fā)指令后都收不到數(shù)據(jù)了,連按多次,只有一次能收到
后來測試了一下,串口收發(fā),發(fā)現(xiàn)代碼中加入延時(shí)后,串口數(shù)據(jù)返回也會(huì)延時(shí),難道延時(shí)會(huì)影響到中斷。。。。。
請大神給看看。。 代碼如下
main.c
  1. /*------------------------------------------------------------------*/
    /* --- STC MCU International Limited -------------------------------*/
    /* --- STC 1T Series MCU RC Demo -----------------------------------*/
    /* --- Mobile: (86)13922805190 -------------------------------------*/
    /* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
    /* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
    /* --- Web: www.GXWMCU.com -----------------------------------------*/
    /* --- QQ:  800003751 ----------------------------------------------*/
    /* If you want to use the program or the program referenced in the  */
    /* article, please specify in which data and procedures from STC    */
    /*------------------------------------------------------------------*/


    #include    "config.h"
    #include    "USART1.h"
    #include    "delay.h"


    /*************    功能說明    **************

    雙串口全雙工中斷方式收發(fā)通訊程序。

    通過PC向MCU發(fā)送數(shù)據(jù), MCU收到后通過串口把收到的數(shù)據(jù)原樣返回.

    ******************************************/

    /*************    本地常量聲明    **************/


    /*************    本地變量聲明    **************/


    /*************    本地函數(shù)聲明    **************/



    /*************  外部函數(shù)和變量聲明 *****************/


    /*************  串口1初始化函數(shù) *****************/
    void    UART_config(void)
    {
        COMx_InitDefine        COMx_InitStructure;                    //結(jié)構(gòu)定義
        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;        //模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer2;            //使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
        COMx_InitStructure.UART_BaudRate  = 115200ul;            //波特率, 一般 110 ~ 115200
        COMx_InitStructure.UART_RxEnable  = ENABLE;                //接收允許,   ENABLE或DISABLE
        COMx_InitStructure.BaudRateDouble = DISABLE;            //波特率加倍, ENABLE或DISABLE
        COMx_InitStructure.UART_Interrupt = ENABLE;                //中斷允許,   ENABLE或DISABLE
        COMx_InitStructure.UART_Polity    = PolityHigh;            //中斷優(yōu)先級, PolityLow,PolityHigh
        COMx_InitStructure.UART_P_SW      = UART1_SW_P30_P31;    //切換端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必須使用內(nèi)部時(shí)鐘)
        COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;        //內(nèi)部短路RXD與TXD, 做中繼, ENABLE,DISABLE
        USART_Configuration(USART1, &COMx_InitStructure);        //初始化串口1 USART1,USART2

        PrintString1("STC15F2K60S2 UART1 Test Prgramme!\r\n");    //SUART1發(fā)送一個(gè)字符串
    }


    /**********************************************/
    void main(void)
    {
        u8    i;

        UART_config();
        EA = 1;

        while (1)
        {
            delay_ms(1);
            Delay200ms();     Delay200ms();Delay200ms();Delay200ms();Delay200ms();
            if(COM1.RX_TimeOut > 0)        //超時(shí)計(jì)數(shù)
            {
                if(--COM1.RX_TimeOut == 0)
                {
                    if(COM1.RX_Cnt > 0)
                    {
                        for(i=0; i<COM1.RX_Cnt; i++)    TX1_write2buff(RX1_Buffer[i]);    //收到的數(shù)據(jù)原樣返回
                    }
                    COM1.RX_Cnt = 0;
                }
            }
        }
    }
usart1.c
  1. /*------------------------------------------------------------------*/
    /* --- STC MCU International Limited -------------------------------*/
    /* --- STC 1T Series MCU RC Demo -----------------------------------*/
    /* --- Mobile: (86)13922805190 -------------------------------------*/
    /* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
    /* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
    /* --- Web: www.GXWMCU.com -----------------------------------------*/
    /* --- QQ:  800003751 ----------------------------------------------*/
    /* If you want to use the program or the program referenced in the  */
    /* article, please specify in which data and procedures from STC    */
    /*------------------------------------------------------------------*/


    #include "USART1.h"


    COMx_Define    COM1;
    u8    idata TX1_Buffer[COM_TX1_Lenth];    //發(fā)送緩沖
    u8     idata RX1_Buffer[COM_RX1_Lenth];    //接收緩沖

    u8 USART_Configuration(u8 UARTx, COMx_InitDefine *COMx)
    {
        u8    i;
        u32    j;
        
        if(UARTx == USART1)
        {
            COM1.id = 1;
            COM1.TX_read    = 0;
            COM1.TX_write   = 0;
            COM1.B_TX_busy  = 0;
            COM1.RX_Cnt     = 0;
            COM1.RX_TimeOut = 0;
            COM1.B_RX_OK    = 0;
            for(i=0; i<COM_TX1_Lenth; i++)    TX1_Buffer[i] = 0;
            for(i=0; i<COM_RX1_Lenth; i++)    RX1_Buffer[i] = 0;

            if(COMx->UART_Mode > UART_9bit_BRTx)    return 1;    //模式錯(cuò)誤
            if(COMx->UART_Polity == PolityHigh)        PS = 1;    //高優(yōu)先級中斷
            else                                    PS = 0;    //低優(yōu)先級中斷
            SCON = (SCON & 0x3f) | COMx->UART_Mode;
            if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))    //可變波特率
            {
                j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;    //按1T計(jì)算
                if(j >= 65536UL)    return 2;    //錯(cuò)誤
                j = 65536UL - j;
                if(COMx->UART_BRT_Use == BRT_Timer1)
                {
                    TR1 = 0;
                    AUXR &= ~0x01;        //S1 BRT Use Timer1;
                    TMOD &= ~(1<<6);    //Timer1 set As Timer
                    TMOD &= ~0x30;        //Timer1_16bitAutoReload;
                    AUXR |=  (1<<6);    //Timer1 set as 1T mode
                    TH1 = (u8)(j>>8);
                    TL1 = (u8)j;
                    ET1 = 0;    //禁止中斷
                    TMOD &= ~0x40;    //定時(shí)
                    INT_CLKO &= ~0x02;    //不輸出時(shí)鐘
                    TR1  = 1;
                }
                else if(COMx->UART_BRT_Use == BRT_Timer2)
                {
                    AUXR &= ~(1<<4);    //Timer stop
                    AUXR |= 0x01;        //S1 BRT Use Timer2;
                    AUXR &= ~(1<<3);    //Timer2 set As Timer
                    AUXR |=  (1<<2);    //Timer2 set as 1T mode
                    TH2 = (u8)(j>>8);
                    TL2 = (u8)j;
                    IE2  &= ~(1<<2);    //禁止中斷
                    AUXR &= ~(1<<3);    //定時(shí)
                    AUXR |=  (1<<4);    //Timer run enable
                }
                else return 2;    //錯(cuò)誤
            }
            else if(COMx->UART_Mode == UART_ShiftRight)
            {
                if(COMx->BaudRateDouble == ENABLE)    AUXR |=  (1<<5);    //固定波特率SysClk/2
                else                                AUXR &= ~(1<<5);    //固定波特率SysClk/12
            }
            else if(COMx->UART_Mode == UART_9bit)    //固定波特率SysClk*2^SMOD/64
            {
                if(COMx->BaudRateDouble == ENABLE)    PCON |=  (1<<7);    //固定波特率SysClk/32
                else                                PCON &= ~(1<<7);    //固定波特率SysClk/64
            }
            if(COMx->UART_Interrupt == ENABLE)    ES = 1;    //允許中斷
            else                                ES = 0;    //禁止中斷
            if(COMx->UART_RxEnable == ENABLE)    REN = 1;    //允許接收
            else                                REN = 0;    //禁止接收
            P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);    //切換IO
            if(COMx->UART_RXD_TXD_Short == ENABLE)    PCON2 |=  (1<<4);    //內(nèi)部短路RXD與TXD, 做中繼, ENABLE,DISABLE
            else                                    PCON2 &= ~(1<<4);
            return    0;
        }
        return 3;    //其它錯(cuò)誤
    }


    /*************** 裝載串口發(fā)送緩沖 *******************************/

    void TX1_write2buff(u8 dat)    //寫入發(fā)送緩沖,指針+1
    {
        TX1_Buffer[COM1.TX_write] = dat;    //裝發(fā)送緩沖
        if(++COM1.TX_write >= COM_TX1_Lenth)    COM1.TX_write = 0;

        if(COM1.B_TX_busy == 0)        //空閑
        {  
            COM1.B_TX_busy = 1;        //標(biāo)志忙
            TI = 1;                    //觸發(fā)發(fā)送中斷
        }
    }

    void PrintString1(u8 *puts)
    {
        for (; *puts != 0;    puts++)  TX1_write2buff(*puts);     //遇到停止符0結(jié)束
    }



    /********************* UART1中斷函數(shù)************************/
    void UART1_int (void) interrupt UART1_VECTOR
    {
        if(RI)
        {
            RI = 0;
            if(COM1.B_RX_OK == 0)
            {
                if(COM1.RX_Cnt >= COM_RX1_Lenth)    COM1.RX_Cnt = 0;
                RX1_Buffer[COM1.RX_Cnt++] = SBUF;
                COM1.RX_TimeOut = TimeOutSet1;
            }
        }

        if(TI)
        {
            TI = 0;
            if(COM1.TX_read != COM1.TX_write)
            {
                 SBUF = TX1_Buffer[COM1.TX_read];
                if(++COM1.TX_read >= COM_TX1_Lenth)        COM1.TX_read = 0;
                
            }
            else    COM1.B_TX_busy = 0;
        }
    }

delay.c
  1. #include    "delay.h"



    //========================================================================
    // 函數(shù): void  delay_ms(unsigned char ms)
    // 描述: 延時(shí)函數(shù)。
    // 參數(shù): ms,要延時(shí)的ms數(shù), 這里只支持1~255ms. 自動(dòng)適應(yīng)主時(shí)鐘.
    // 返回: none.
    // 版本: VER1.0
    // 日期: 2013-4-1
    // 備注:
    //========================================================================
    void  delay_ms(unsigned char ms)
    {
         unsigned int i;
         do{
              i = MAIN_Fosc / 13000;
              while(--i)    ;   //14T per loop
         }while(--ms);
    }

    void Delay200ms()        //@22.1184MHz
    {
        unsigned char i, j, k;

        _nop_();
        _nop_();
        i = 17;
        j = 208;
        k = 27;
        do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }




benli 2015-07-18 15:30
贊助商鏈接

這個(gè)代碼寫的太難讀懂了?。。。。?!

我是鑫鑫 2015-07-18 15:31
贊助商鏈接

那樣寫的串口模塊占用空間好大呀

#include <reg51.h>

void InitUART(void)
{
    TMOD = 0x20;
    SCON = 0x50;
    TH1 = 0xFD;
    TL1 = TH1;
    PCON = 0x00;
    EA = 1;
    ES = 1;
    TR1 = 1;
}

void SendOneByte(unsigned char c)
{
    SBUF = c;
    while(!TI);//等待發(fā)送完成
    TI = 0;
}

void main(void)
{
    InitUART();
}

void UARTInterrupt(void) interrupt 4
{

}

abv123 2015-07-18 15:37
我是鑫鑫:那樣寫的串口模塊占用空間好大呀
#include <reg51.h>
void InitUART(void)
....... (2015-07-18 15:31) 

能給看看為什么嗎?為什么延時(shí)會(huì)影響到串口?

abv123 2015-07-18 15:38
我是鑫鑫:那樣寫的串口模塊占用空間好大呀
#include <reg51.h>
void InitUART(void)
....... (2015-07-18 15:31) 

心片是stc15w408as,stc15w408as,五個(gè)字

abv123 2015-07-18 17:56
頂一下頂一下

firstbird 2015-07-18 20:23
串口操作太慢了,何不浪費(fèi)點(diǎn)空間定義成隊(duì)列,用時(shí)鐘中斷定時(shí)發(fā)送。

benli 2015-07-18 20:36
原樣返回幾句代碼就行了啊?。?br>void UARTInterrupt(void) interrupt 4
{
    if(RI)
        SBUF=SBUF;
    if(TI)
        TI=0;
}

abv123 2015-07-18 20:58
benli:原樣返回幾句代碼就行了?。?!
void UARTInterrupt(void) interrupt 4
{
    if(RI)
        SBUF=SBUF;
....... (2015-07-18 20:36) 

我按您這個(gè)試了一下,當(dāng)我發(fā)一個(gè)字符后,程序返回0xff進(jìn)入了死循環(huán)

chenlei1910 2015-07-18 22:25
會(huì)影響    到最好用定時(shí)完成延時(shí)動(dòng)作

a978019543 2015-07-19 09:59
來學(xué)習(xí)學(xué)習(xí),新手覺得這個(gè)C51略難學(xué)

磨星 2015-07-19 11:22
這個(gè)程序功能是這樣的:

以中斷方式接收數(shù)據(jù),存放于一個(gè)數(shù)組并計(jì)數(shù)收到字符個(gè)數(shù)。
每接收到一個(gè)字符都延時(shí)一個(gè)固定的時(shí)間TimeOutSet1 , 單位是秒。這個(gè)時(shí)間過了,就當(dāng)作發(fā)送方已經(jīng)發(fā)送完畢,于是單片機(jī)開始轉(zhuǎn)發(fā)。

轉(zhuǎn)發(fā)前,數(shù)據(jù)是從接收的數(shù)組拷貝到另一個(gè)發(fā)送數(shù)組。發(fā)送數(shù)組有點(diǎn)環(huán)形緩沖的味道。

拷貝完成后,人工觸發(fā)發(fā)送中斷 , 在中斷部分逐個(gè)發(fā)出。

磨星 2015-07-19 11:26
頂樓的程序從風(fēng)格上講,似乎是PC編程經(jīng)驗(yàn)比較豐富的人寫的。樓主應(yīng)該是拿人家的例子過來改,不過把控不住。

這里面太多坑了!

磨星 2015-07-19 12:15
首先TimeOutSet1 不能設(shè)大,否則一方面延遲太久 , 還沒發(fā)出去呢, 要是對方期間又發(fā)來數(shù)據(jù) ,還得又等很長時(shí)間。就會(huì)懷疑是不是發(fā)送不成功。其實(shí)一直在等呢。

要命的是,這段期間接收的數(shù)據(jù)個(gè)數(shù)超過了數(shù)組大小 , 前面的要么被完全清空(COM1.RX_Cnt歸零),要么只留下部分(COM1.RX_Cnt歸零后繼續(xù)計(jì)數(shù))。 反正是不正確了。

接收后的拷貝到發(fā)送數(shù)組過程中,如果對方又發(fā)來數(shù)據(jù) , 極端情況是這樣的:
         for(i=0; i<COM1.RX_Cnt; i++)    TX1_write2buff(RX1_Buffer);    //收到的數(shù)據(jù)原樣返回

       for循環(huán)中,也就是 i > 0 了 , COM1.RX_Cnt恰好歸零! 你看看for能正確嗎。




磨星 2015-07-19 13:29
我建議,如果不是特別有把握 , 還是盡量避免在中斷和主程序共用變量,能不用中斷方式更好。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多