菜鸟求51单片串口编程中断方式发送字符串代码!!

milanmaldini   2009-9-27 20:02 楼主
单片机为51单片机,编程语言为Keil C51
问题如下:
我从串口接收6字节的字符串,然后将其原封不动的发还给源端,因为主程序机时的限制,无法用查询方式发送,必须在串口中断中发送。
问题急待解决,我的代码现在无法解决这个问题,请哪位大侠伸手拉我一把,先在这里谢了。下面是我的串口中断代码:
void UartInterrupt(void) interrupt 4 using 3
{
        unsigned char dat;
       
        if(RI)
        {
                RI = 0;
                dat = SBUF;
                scount = 0;

                if(rstart)
                {
                        if(dat == 0xfd && rcount == 5)
                        {
                                DBuff[5] = dat;
                                recieved = 1;
                                rstart = 0;
                                if(DBuff[4] == (DBuff[2] ^ DBuff[3]))
                                {
                                        SBUF = DBuff[0];
                                        scount = 1;
                                }
                        }
                        else if(dat == 0xfe)
                        {
                                DBuff[0] = dat;
                                rcount = 1;
                        }
                        else
                        {
                                if(rcount < 5)
                                {
                                        DBuff[rcount++] = dat;
                                }
                                else
                                {
                                        rcount = 0;
                                        rstart = 0;
                                }
                        }
                }
                else
                {
                        if(dat == 0xfe)
                        {       
                                DBuff[0] = dat;
                                rcount = 1;
                                rstart = 1;
                        }
                }
        }

        if(TI)
        {
                if(scount < 6)
                {
                        SBUF = DBuff[scount];
                        TI = 0;
                        scount ++;
                }
                else
                {
                        scount = 0;
                        TI = 0;
                }
        }
}

回复评论 (9)

IF (TI)

后面那个ELSE就不要了吧?

你装好数据后

TI = 1;
点赞  2009-9-27 20:40
先试试
点赞  2009-9-27 20:40
serialconfig.h

  1. #ifndef _SERIAL_CONFIG_H_
  2. #define _SERIAL_CONFIG_H_
  3. #include "const.h"
  4. #include "oscfrequencydef.h"

  5. #ifndef OSC_FREQUENCY
  6. #error undefined OSC_FREQUENCY
  7. #endif

  8. /******************************************************************************
  9. 仅限于:
  10. 串口方式1的工作模式,即1位起始位,8位数据位和1位停止位,无校验位,波特率不倍增
  11. ******************************************************************************/

  12. typedef enum tagBAUD
  13. {
  14.         b_1200 = 1200,
  15.         b_2400 = 2400,
  16.         b_4800 = 4800,
  17.         b_9600 = 9600,
  18. //        b_19200 = 19200,

  19.         INVALID_BAUD,

  20. }BAUD;


  21. typedef void (*RECVPROC)(BYTE byte);

  22. BOOL OpenSerial(BAUD Baud, RECVPROC pRecvFunc);
  23. BOOL SendData(const BYTE* pData, BYTE nSize);
  24. void CloseSerial();


  25. #endif




serialconfig.c

  1. #include "serialconfig.h"
  2. #include "chiptypedef.h"
  3. #include
  4. #include

  5. RECVPROC g_pfnRecvFunc = NULL;


  6. BOOL OpenSerial(BAUD Baud, RECVPROC pRecvFunc)
  7. {

  8.         BYTE LoadValue = 0;

  9.         if(pRecvFunc == NULL)
  10.                 return FALSE;
  11.                
  12.         g_pfnRecvFunc = pRecvFunc;

  13.         switch(Baud) //确保输入的波特率是正确的
  14.         {
  15.                 case b_1200:
  16.                 case b_2400:
  17.                 case b_4800:
  18.                 case b_9600:
  19.                         break;

  20.                 default:
  21.                         return FALSE;
  22.                         break;
  23.         }       
  24.                
  25.         /*****************************************************************************
  26.         LoadValue = 256 -        OSC_FREQUENCY * 10^6 / (384 * Baud)
  27.         因每次运算的结果上限限制,故做了变换
  28.         ******************************************************************************/       
  29.         LoadValue = 256 - (BYTE)(1000 * 1.0f * (float)OSC_FREQUENCY / 384 * 1000 * 1.0f / Baud);



  30.         TMOD |= T1_M1_;        //定时器T1工作方式2
  31.         TH1 = LoadValue;               
  32.         TL1 = LoadValue;   //不可TL1 = TH1赋值
  33.         PCON = 0x00;        //波特率不倍增   
  34.         SCON = 0x50;        //串行通信方式1,允许接收       
  35. //        SM1 = 1;
  36. //        REN = 1;
  37.           
  38.         TR1 = 1;                //启动定时器1
  39.         ES = 1;                        //开串行中断  
  40.         EA = 1;         //开总中断

  41.         return TRUE;
  42. }

  43. void CloseSerial()
  44. {
  45.         TR1 = 0;                //关定时器1
  46.         ES = 0;                        //关串行中断  
  47. }

  48. BOOL SendData(const BYTE* pData, BYTE nSize)
  49. {
  50.         BYTE i = 0;
  51.         /**********************************************
  52.         执行连续的串口发送命令需要禁止中断干扰,否则
  53.         发出去的数据混乱!!但具体原因不清楚
  54.         ***********************************************/
  55. //         EA = 0;
  56.         if(pData == NULL || nSize == 0)
  57.                 return FALSE;

  58.         for(i = 0; i < nSize; i++)
  59.         {
  60.                 SBUF = pData[i];
  61.                 while(!TI);
  62.                 TI = 0;
  63.         }
  64.        
  65. //        EA = 1;       

  66.         return TRUE;
  67. }

  68. void SerialISR() interrupt SIO_VECTOR
  69. {
  70.         RI = 0;
  71.         (*g_pfnRecvFunc)(SBUF);
  72. }

点赞  2009-9-27 21:52
必须在串口中断中发送。
点赞  2009-9-27 22:21
/******************************************************************************
仅限于:
串口方式1的工作模式,即1位起始位,8位数据位和1位停止位,无校验位,波特率不倍增
******************************************************************************/

typedef enum tagBAUD
{
    b_1200 = 1200,
    b_2400 = 2400,
    b_4800 = 4800,
    b_9600 = 9600,
//    b_19200 = 19200,

    INVALID_BAUD,

}BAUD;


如果工作在115200怎么办?
点赞  2009-9-27 22:23
引用: 引用 5 楼 lbing7 的回复:
/******************************************************************************
仅限于:
串口方式1的工作模式,即1位起始位,8位数据位和1位停止位,无校验位,波特率不倍增
******************************************************************************/

typedef enum tagBAUD
{
? ? b_1200 = 1200,
? ? b_2400 = 2400,
? ? b_4800 = 4800,
? ? b_9600 = 9600,
//? ? b_19200 = 19200,

? ? INVALID_BAUD,

}BAUD;


如果工作在115200怎么办?

没问题,但是需要自己改动一些设置。因为我用的串口一般9600足矣。
点赞  2009-9-28 17:34
enmu的数据类型本质是啥?

有多少长度?不溢出?

是哈,据说以前有一个视频语音通信系统的通信速率才1200呢

点赞  2009-9-28 20:05
引用: 引用 7 楼 lbing7 的回复:
enmu的数据类型本质是啥?

有多少长度?不溢出?

是哈,据说以前有一个视频语音通信系统的通信速率才1200呢

你sizeof一下自然就知道了。
在keil的帮助文档里写的很清楚:The enum keyword defines set of constants of type char or type int depending on the range of values of the set.
点赞  2009-9-29 16:54
谢谢jiqiang,问题我现在解决了,发送还是利用主程序发送的。楼上的代码发送字节的代码估计也需要在主函数中调用。不过帖子我还是结了,还望高手们以后对我多多帮助。
点赞  2009-10-26 09:35
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复