打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
STC延时会影响串口中断收发??|我爱单片机
各位,我在写一个串口通信的程序,代码写的比较长之后,发现串口收发变的不正常了
开始表现为,发指令后,接收数据延后,接着写功能代码,到最后发现,发指令后都收不到数据了,连按多次,只有一次能收到
后来测试了一下,串口收发,发现代码中加入延时后,串口数据返回也会延时,难道延时会影响到中断。。。。。
请大神给看看。。 代码如下
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"


    /*************    功能说明    **************

    双串口全双工中断方式收发通讯程序。

    通过PC向MCU发送数据, MCU收到后通过串口把收到的数据原样返回.

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

    /*************    本地常量声明    **************/


    /*************    本地变量声明    **************/


    /*************    本地函数声明    **************/



    /*************  外部函数和变量声明 *****************/


    /*************  串口1初始化函数 *****************/
    void    UART_config(void)
    {
        COMx_InitDefine        COMx_InitStructure;                    //结构定义
        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;            //中断优先级, PolityLow,PolityHigh
        COMx_InitStructure.UART_P_SW      = UART1_SW_P30_P31;    //切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)
        COMx_InitStructure.UART_RXD_TXD_Short = DISABLE;        //内部短路RXD与TXD, 做中继, ENABLE,DISABLE
        USART_Configuration(USART1, &COMx_InitStructure);        //初始化串口1 USART1,USART2

        PrintString1("STC15F2K60S2 UART1 Test Prgramme!\r\n");    //SUART1发送一个字符串
    }


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

        UART_config();
        EA = 1;

        while (1)
        {
            delay_ms(1);
            Delay200ms();     Delay200ms();Delay200ms();Delay200ms();Delay200ms();
            if(COM1.RX_TimeOut > 0)        //超时计数
            {
                if(--COM1.RX_TimeOut == 0)
                {
                    if(COM1.RX_Cnt > 0)
                    {
                        for(i=0; i<COM1.RX_Cnt; i++)    TX1_write2buff(RX1_Buffer[i]);    //收到的数据原样返回
                    }
                    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];    //发送缓冲
    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;    //模式错误
            if(COMx->UART_Polity == PolityHigh)        PS = 1;    //高优先级中断
            else                                    PS = 0;    //低优先级中断
            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计算
                if(j >= 65536UL)    return 2;    //错误
                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;    //定时
                    INT_CLKO &= ~0x02;    //不输出时钟
                    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);    //定时
                    AUXR |=  (1<<4);    //Timer run enable
                }
                else return 2;    //错误
            }
            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);    //内部短路RXD与TXD, 做中继, ENABLE,DISABLE
            else                                    PCON2 &= ~(1<<4);
            return    0;
        }
        return 3;    //其它错误
    }


    /*************** 装载串口发送缓冲 *******************************/

    void TX1_write2buff(u8 dat)    //写入发送缓冲,指针+1
    {
        TX1_Buffer[COM1.TX_write] = dat;    //装发送缓冲
        if(++COM1.TX_write >= COM_TX1_Lenth)    COM1.TX_write = 0;

        if(COM1.B_TX_busy == 0)        //空闲
        {  
            COM1.B_TX_busy = 1;        //标志忙
            TI = 1;                    //触发发送中断
        }
    }

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



    /********************* UART1中断函数************************/
    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"



    //========================================================================
    // 函数: void  delay_ms(unsigned char ms)
    // 描述: 延时函数。
    // 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
    // 返回: 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);
    }




benli2015-07-18 15:30
赞助商链接

这个代码写的太难读懂了!!!!!!

我是鑫鑫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);//等待发送完成
    TI = 0;
}

void main(void)
{
    InitUART();
}

void UARTInterrupt(void) interrupt 4
{

}

abv1232015-07-18 15:37
我是鑫鑫:那样写的串口模块占用空间好大呀
#include <reg51.h>
void InitUART(void)
....... (2015-07-18 15:31) 


能给看看为什么吗?为什么延时会影响到串口?

abv1232015-07-18 15:38
我是鑫鑫:那样写的串口模块占用空间好大呀
#include <reg51.h>
void InitUART(void)
....... (2015-07-18 15:31) 


心片是stc15w408as,stc15w408as,五个字

abv1232015-07-18 17:56
顶一下顶一下

firstbird2015-07-18 20:23
串口操作太慢了,何不浪费点空间定义成队列,用时钟中断定时发送。

benli2015-07-18 20:36
原样返回几句代码就行了啊!!
void UARTInterrupt(void) interrupt 4
{
    if(RI)
        SBUF=SBUF;
    if(TI)
        TI=0;
}

abv1232015-07-18 20:58
benli:原样返回几句代码就行了啊!!
void UARTInterrupt(void) interrupt 4
{
    if(RI)
        SBUF=SBUF;
....... (2015-07-18 20:36) 


我按您这个试了一下,当我发一个字符后,程序返回0xff进入了死循环

chenlei19102015-07-18 22:25
会影响    到最好用定时完成延时动作

a9780195432015-07-19 09:59
来学习学习,新手觉得这个C51略难学

磨星2015-07-19 11:22
这个程序功能是这样的:

以中断方式接收数据,存放于一个数组并计数收到字符个数。
每接收到一个字符都延时一个固定的时间TimeOutSet1 , 单位是秒。这个时间过了,就当作发送方已经发送完毕,于是单片机开始转发。

转发前,数据是从接收的数组拷贝到另一个发送数组。发送数组有点环形缓冲的味道。

拷贝完成后,人工触发发送中断 , 在中断部分逐个发出。

磨星2015-07-19 11:26
顶楼的程序从风格上讲,似乎是PC编程经验比较丰富的人写的。楼主应该是拿人家的例子过来改,不过把控不住。

这里面太多坑了!

磨星2015-07-19 12:15
首先TimeOutSet1 不能设大,否则一方面延迟太久 , 还没发出去呢, 要是对方期间又发来数据 ,还得又等很长时间。就会怀疑是不是发送不成功。其实一直在等呢。

要命的是,这段期间接收的数据个数超过了数组大小 , 前面的要么被完全清空(COM1.RX_Cnt归零),要么只留下部分(COM1.RX_Cnt归零后继续计数)。 反正是不正确了。

接收后的拷贝到发送数组过程中,如果对方又发来数据 , 极端情况是这样的:
         for(i=0; i<COM1.RX_Cnt; i++)    TX1_write2buff(RX1_Buffer);    //收到的数据原样返回

       for循环中,也就是 i > 0 了 , COM1.RX_Cnt恰好归零! 你看看for能正确吗。




磨星2015-07-19 13:29
我建议,如果不是特别有把握 , 还是尽量避免在中断和主程序共用变量,能不用中断方式更好。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
STC8A8K64D4开发板第2串口通信掌握USB转串口电路的原理和设计
编程点滴:AVR的I/O端口模拟UART串口测试程序
【六足-智能】串口调试
51单片机串口通信使用类似printf函数的两种办法
STC12C5A60S2单片机A/D转换函数C语言程序模板
Zigbee之旅(十):综合小实验——基于CC2430的温度监测系统(转)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服