搜索
bottom↓
回复: 72

关于MCU串口中断接收,以及缓存发送大量数据的问题,高手进

[复制链接]

出0入0汤圆

发表于 2010-4-12 10:27:11 | 显示全部楼层 |阅读模式
需要利用串口接收DET的大量数据,存于缓存后将数据转发给PC,请问高手怎么做这个中断机制以及如何处理对缓冲区数据的读取比较合适呢?
我的数据一包200个字节,有包头和固定的数据长度。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2010-4-12 10:33:20 | 显示全部楼层
void REV() interrupt 4
{
        unsigned char i;
  if(RI==1)
        {  
                ES=0;
                RI=0;
                rx_buf=SBUF;
                if(rx_buf==0xAA)//包头
                {
                        i++;
                        if(i==199)
                        {
                                revfinish=1;//接收完成 发送
                        }
                }
                else
                        {
                                i=0;
                        }
                ES=1;
  }

出0入0汤圆

 楼主| 发表于 2010-4-12 10:33:53 | 显示全部楼层
楼上的这种方式不合理吧?

出0入0汤圆

发表于 2010-4-12 17:43:30 | 显示全部楼层
接收计数i要定义成全局或静态变量,而且你这样写包头包尾没起作用,临时写一段,接收计数你测试时注意下,我可能数错了--!

#define  REC_MAX   200

#define  CHECK_HEAD  0xFF         //  随便定义的包头
#define  CHECK_TAIL  0xF0


volatile uchar Rec_Len;         //  接收计数
volatile uchar Rec_Flag;         //  接收标志

xdata    uchar DataBuf[REC_MAX]; // 缓存

void Initial_Serial(void)        // 串口初始化
{
    ....
    Rec_Len  = 0;            // 初始接收长度为0
    Rec_Flag = 0;            // 未接收 0 未接收或接收完成 1 开始接收
    ....
}

void Uart_Rec(void)   interrupt 4
{
    uchar sbuffer;

    if(RI)
    {
        RI = 0;
        sbuffer = SBUF;

        if((sbuffer == CHECK_HEAD) && (Rec_Flag == 0))  // 如果收到文件头而且当前未接收
        {
            Rec_Flag = 1;
            Rec_Len  = 0;
            DataBuf[0] = sbuffer;                // 这里保留了包头
        }   
        else if(Rec_Flag)                            // 开始接收
        {
            if(Rec_Len < (REC_MAX - 1))  
            {
                Rec_Len++;
                DataBuf[Rec_Len] = sbuffer;       // 当数据送缓冲区
            }
            else if(Rec_Len == (REC_MAX - 1))      //  接收完成 
            {
        if(DataBuf[Rec_Len] == CHECK_TAIL)
                {
                    ....         //  表明接收成功未出错
                }
                else
                {
                    ....         //  有误码
                }
                Rec_Flag = 0;  // 接收完成,标志清0
            }
        }
    }
}

真难对齐....
忘加注释了--!,给你加上,哥人品一向很好,代码临时写的你测试下,大致思路是这样的。
好像写的有点长

出0入0汤圆

发表于 2010-4-15 12:59:48 | 显示全部楼层
楼主的代码有问题
建议:
  1.中断里只负责将寄存器的值转存到缓存中
  2.如有必要,可以在中断里判断包头和包未,设置相应标志,处理则应该交由主程序处理

出0入8汤圆

发表于 2010-4-15 19:46:07 | 显示全部楼层
下面仅供参考...

(原文件名:c790eb49.JPG)

出0入0汤圆

 楼主| 发表于 2010-4-21 16:43:39 | 显示全部楼层
不好意思,抗震救灾刚回来,有劳楼上诸位了。
amazing030 兄弟的程序结构很严谨,不过没有置发送标志位吧,然而这种接受和发送方式适合每包数据200bytes的数据传输么?可否将主程序里的发送机制也做出来呢?也好让鄙人能理解您的思路。


谢谢martal的建议。




不太明白security 的超时等待什么意思,我只是想接收数据放缓存,接受完毕调用,然后清空。


希望还能得到诸位的答复,谢谢。

出0入0汤圆

发表于 2010-5-3 22:03:54 | 显示全部楼层
我是菜鸟,也正在学习正在学习这种编程思想,谢谢各位的指点!

出0入0汤圆

发表于 2010-5-4 17:47:11 | 显示全部楼层
那段代码只是我临时写的,只是大致思路而路。
重点是:
1.判断出包头
 这里由接收完成标志Rec_Flag确认,Rec_Flag未接收/接收完成时置0,当Rec_Flag为0且接收字符为包头时开始接收,若Rec_Flag为1则表明接收的为数据,这是为了防止包头和接收数据相同时判断错误。
2.接收计数 
 这里由接收计数变量Rec_Len确认,在未接收到校验尾/包尾时计数
3.判断包尾/检验
 当接收Rec_Len溢出时(即接收到指定长度数据),如果最后一位数据与包尾相同则表明接收成功。一般包尾只是判断接收完成,还有一位用来判断接收成功与否,即校验位,需对所接收的数据进行校验计算,如非必要最好不要在中断中进行。只有校验成功(有别于接收成功)才可对数据进行目标操作。

数据长短这个只是怕传输出错,和处理关系不大,但最好有检验位。也可拆成几段短的数据发送。

TI可以不置位,因为没给发送SBUF装值,你不放心的话再加上一段
if(RI)
{
...
}
else
{
    if(TI)
        TI = 0;
}
以上只是个人的拙见,欢迎拍砖,共同提高

出0入0汤圆

发表于 2010-5-4 17:49:46 | 显示全部楼层
另外,对自称哥表示歉意,本人88年的..只是最近网上哥太多

出0入8汤圆

发表于 2010-5-5 18:56:47 | 显示全部楼层
回复【6楼】renjun861214
不好意思,抗震救灾刚回来,有劳楼上诸位了。
amazing030 兄弟的程序结构很严谨,不过没有置发送标志位吧,然而这种接受和发送方式适合每包数据200bytes的数据传输么?可否将主程序里的发送机制也做出来呢?也好让鄙人能理解您的思路。
谢谢martal的建议。

不太明白security 的超时等待什么意思,我只是想接收数据放缓存,接受完毕调用,然后清空。
希望还能得到诸位的答复,谢谢。
-----------------------------------------------------------------------


关于5楼的 程序伪代码,适用在有额外空闲定时器的情况,你可以在主进程中,分析协议,然后再发送。
这里关于 程序伪代码 中的超时等待,我从Win32 串口驱动,引申说明下原理:
Win32 串口操作涉及到的超时数据结构
typedef   struct   _COMMTIMEOUTS   {     
      DWORD   ReadIntervalTimeout;          //   读间隔超时   
      DWORD   ReadTotalTimeoutMultiplier;   //   读时间系数   
      DWORD   ReadTotalTimeoutConstant;     //   读时间常量   
      DWORD   WriteTotalTimeoutMultiplier;  //   写时间系数   
      DWORD   WriteTotalTimeoutConstant;    //   写时间常量   
  } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
具体各个成员的含义,可以百度下,会有较详细的介绍的。
我这里只是想 着重 点出 ReadIntervalTimeout,这里实际跟 5楼的 程序伪代码 说到超时是一样。
即:ReadIntervalTimeout 指在接收时两个字符之间的最大延时,一旦连续的两个字符传输的时间差超过ReadIntervalTimeout该值,将发生超时,返回已经接受到缓冲的数据,这时系统再对该数据进行解析,处理。

出0入0汤圆

发表于 2010-8-20 17:06:25 | 显示全部楼层
mark.

出0入0汤圆

发表于 2010-8-20 19:03:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-31 20:46:02 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-10-31 22:11:28 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-11-12 23:27:43 | 显示全部楼层
用个环形缓冲区会不会好点呢,一定要打包在一起吗?

出0入0汤圆

发表于 2010-11-13 09:27:27 | 显示全部楼层
本人多年来一直用的都是amazing030兄弟的差不多的思路,简单易理解,呵呵

出0入0汤圆

发表于 2010-11-13 09:46:26 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-11-16 15:33:11 | 显示全部楼层
回复【9楼】amazing030
-----------------------------------------------------------------------

老兄,加个QQ540125095,我想咨询一下这方面的问题。。谢谢了

出0入0汤圆

发表于 2010-11-16 15:55:12 | 显示全部楼层
回复【8楼】amazing030  
-----------------------------------------------------------------------

回复【楼主位】renjun861214  
-----------------------------------------------------------------------

网络上有很多参考,你可以看看77e58双串口的参考代码。最简单有效的是在内存中开辟数据池,中断函数只负责收发数据,不做任何判断。形象点说就是中断函数就是水池进水、出水阀门,其他一概不管。数据的提取通过其他函数完成。

出0入0汤圆

发表于 2010-11-16 18:04:21 | 显示全部楼层
再贴上一段环链方式处理的,就是楼上所说的这样。但有时实时要求高的不怎么适用。因为我定的这个协议长度不固定,每收到一个数据都要判断....

#include    "includes.h"

/**************************** 发送指令格式 *************************************
帧格式: 帧头  接收方地址  发送方地址  帧长  命令字  数据域 校验和
字节数:  2         1           1        1      1       N      1

帧头:      两个特殊字节 0x55 0xAA
接收方地址:通讯对象地址
发送方地址:通讯主机地址 / 为分机之间可通讯扩展
帧长:      从 命令 到 校验和 的字节数 不包含校验和 为 N + 1
命令字:    操作内容
数据域:    命令相关数据
校验和:    命令字 与 数据域 的算术和

/**************************** 返回指令格式 *************************************

09/14测试通过

*/

#define     SELF_ADDR       0x03

#define     TXD_MAX         32
#define     RCV_MAX         32

#define     GET_CONNECT     0x00    // 0号命令用于检测设备连接 分机接收到此命令则返回特定命令以示连接
#define     READ_ADDR       0x01    // 1号命令用于读取设备的编号  只能一对一识别设备时使用 否则无效
#define     READ_CUR        0x02    // 2号命令用于读取指定设备电流
#define     READ_VOL        0x03    // 3号命令用于读取指定设备电压

volatile INT8U   TxdBuf[TXD_MAX];   // 发送缓存
INT8U    TxdPtr;                    // 发送指针 指向将要发送的字节
INT8U    TxdCnt;                    // 发送字节计数

volatile INT8U  RcvBuf[RCV_MAX];    // 接收缓存
volatile INT8U  SavePtr;            // 接收存储指针
volatile INT8U  GetPtr;             // 接收缓存读取指针
volatile INT8U  StartPtr;           // 识别出命令字对应的指针
volatile INT8U  EndPtr;             // 根据帧长计算出帧结束地址

INT8U    DataLen;

BOOLEAN  Rcvbit;                    // 串口收到一个字节标志,为减少变量交互。
BOOLEAN  StartRcv;                  // 开始接收数据帧标志                              

void Device_Init(void)
{
    SavePtr = 0;
    GetPtr  = 0;
    Rcvbit  = 0;
    StartRcv= 0;
}
                                       
void ISR_Uart0(void)    interrupt 4
{
    if(RI0)
    {
        RI0 = 0;
        RcvBuf[SavePtr] = SBUF0;
        SavePtr = (SavePtr + 1) & (RCV_MAX - 1);
        Rcvbit = 1;
    }   
    if(TI0)
    {
        TI0 = 0;
        TxdCnt--;
        if(TxdCnt > 0)
        {
            TxdPtr++;
            SBUF0 = TxdBuf[TxdPtr];
        }
    }
}

BOOLEAN Cmd_Adjust(void)
{
    INT8U i, j, k;
    BOOLEAN flag = 0;

    while(GetPtr != SavePtr)
    {
        if(!StartRcv)
        {
            k = 0;
            
            i = (GetPtr - 5) & (RCV_MAX - 1);
            if(RcvBuf == 0x55)
                k++;
            i = (GetPtr - 4) & (RCV_MAX - 1);
            if(RcvBuf == 0xAA)
                k++;
            i = (GetPtr - 3) & (RCV_MAX - 1);
            if(RcvBuf == SELF_ADDR)
                k++;
            if(k == 3)
            {
                StartRcv = 1;
                i = (GetPtr - 1) & (RCV_MAX - 1);
                DataLen = RcvBuf;
                StartPtr = GetPtr;
                EndPtr = (GetPtr + DataLen) & (RCV_MAX - 1);
            }
        }
        else    //开始接收数据处理
        {
            if(GetPtr == EndPtr)
            {
                StartRcv = 0;   // 数据帧接收完成
                j = StartPtr;
                k = 0;
                for(i = 0; i < DataLen; i++)        // 计算校验和
                {      
                    k += RcvBuf[j];
                    j = (j + 1) & (RCV_MAX - 1);
                }
                k = ~k;
                if(k == RcvBuf[j])
                    flag = 1;
            }
        }
        GetPtr = (GetPtr + 1) & (RCV_MAX - 1);
    }
    return flag;
}

void Deal_Cmd(void)
{
    INT8U cmd;

    cmd = RcvBuf[StartPtr];
    switch(cmd)
    {
        case GET_CONNECT:
            Display_String(40, 2, "Connect..", ASC_6x8,  0);
            break;         
        case READ_ADDR:
            Display_String(40, 2, "Read Addr", ASC_6x8,  0);
            break;
        case READ_CUR:
            Display_String(40, 2, "Read Cur ", ASC_6x8,  0);
            break;
        case READ_VOL:
            Display_String(40, 2, "Read Vol ", ASC_6x8,  0);            
            break;
        default:
            break;
    }
}

出0入0汤圆

发表于 2010-11-16 20:22:29 | 显示全部楼层
学习了

出0入0汤圆

发表于 2010-11-16 21:36:46 | 显示全部楼层
打个记号

出0入0汤圆

发表于 2010-11-16 22:06:20 | 显示全部楼层
MARK!

出0入0汤圆

发表于 2010-11-29 10:49:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-29 11:13:09 | 显示全部楼层
索性再贴一段


//-------------- 串口1接收中断  我用的是C8051F020 ---------------//
void Uart1_Interrupt (void) interrupt 20
{
    if ((SCON1 & 0x01) == 0x01)     // RI1 = 1;
    {
        SCON1  &= 0xFE;             // RI1 = 0;

        TR0 = 0;                    // 关闭定时器

        Uart1_RcvBuf[Uart1_SavePtr++] = SBUF1;

        TH0 = 0x28;                 // 这里设置超时时间 视波特率及通信方式而定 别按我的这个设定。。。单片机也不一样。。。
        TL0 = 0x00;     
        TR0 = 1;                    // 开启定时器
    }
    if((SCON1 & 0x02) == 0x02)                      // Check if transmit flag is set
        SCON1 = (SCON1 & 0xFD);
}

//---------------------- 定时器中断 --------------------------//
void ISR_Timer0(void)   interrupt 1
{
    TR0 = 0;        // 关闭计数

    LED = !LED;
    Rcvbit = 1;     // 置接收标志位
    //TH0 = 0x28;   //
    //TL0 = 0x00;
    //TR0 = 1;      // 这里不使能 装值可在这里重装 保证一次接收后才置一次接收位
}


把我写的GPS接收函数也一并贴出来.....用超时处理的方式处理GPS数据很好使,因为GPS数据每一秒发送一次,每次有大概400Byte的数据,开辟一个缓冲区后等待超时后再处理,9600bps下每秒
9600bit = 1200Byte(实际1000左右) 传送完需大概1/3秒的时间,剩下就是处理和调度的时间了,用51RAM大一些的话也能很好的处理完而不用在中断中处理那么一大堆处理。

typedef struct
{
    INT8U Block;
    INT8U BlockIndex;
    INT8U UTCTime[10];      // hhmmss.mmm
    INT8U Status;           // A- 有效定位 V-无效定位
    INT8U Latitude[9];      // ddmm.mmmm
    INT8U NS;               // N/S
    INT8U Longitude[10];    // dddmm.mmmm
    INT8U EW;               // E/W
    INT8U Speed[5];         // 速率000.0~999.9节
    INT8U Course[5];        // 航向000.0~359.9度
    INT8U UTCDate[6];       // ddmmyy
}stru_GPSRMC;

typedef struct
{
    INT8U Block;            
    INT8U BlockIndex;
    //INT8U UTCTime[10];    // hhmmss.mmm RMC中已有, 所以不解析
    //INT8U Latitude[9];    // ddmm.mmmm
    //INT8U NS;             // N/S
    //INT8U Longitude[10];  // dddmm.mmmm
    //INT8U EW;             // E/W
    INT8U PositionFix;      // 0,1,2,6
    INT8U SateUsed[2];      // 00~12
    //INT8U HDOP[4];        // 0.5~99.9
    INT8U Altitude[7];      // -9999.9~99999.9
}stru_GPSGGA;

typedef struct
{
    INT8U Block;
    INT8U BlockIndex;
    INT8U Mode;             // A-自动 /M-手动  
    INT8U Mode2;            // 0,1,2,3
    INT8U SateUsed[12][2];         
    INT8U PDOP[4];
    INT8U HDOP[4];
    INT8U VDOP[4];
}stru_GPSGSA;

typedef struct
{
    INT8U SatelliteID[2];   // 卫星编号
    INT8U Elevation[2];     // 0-90 degree  // 不显示GPS卫星的方位图, 所以不解析, 节省 5*12 RAM
    INT8U Azimuth[3];       // 0-359 degree // 需要解析时去除注释'//'和解析前的'//'即可
    INT8U SNR[2];           // 0-99 dbHz
}stru_SatelliteInfo;

typedef struct
{
    INT8U Block;
    INT8U BlockIndex;
    INT8U SateInView[2];
    INT8U GSVID;            //当前 GSV语句编号
    stru_SatelliteInfo SatelliteInfo[12];
}stru_GPSGSV;

INT8U GPRMC_Receive(void)
{
    INT8U buf[13];
    INT8U sbuf;
    INT8U *ptr;
    INT16U index;

    memset(&GPS_RMC_Data, 0x00, sizeof(GPS_RMC_Data));  // 每次处理前将结构体清零
    index = Find_Str(Uart1_RcvBuf, "$GPRMC,");
    if(index)
    {
        ptr = Uart1_RcvBuf  + index + 6;
        do
        {
            sbuf = *ptr++;
            switch(sbuf)
            {
                case ',':       // 接收到数据段分隔符','                           
                    GPS_RMC_Data.Block++;                   // 数据段标志
                    GPS_RMC_Data.BlockIndex = 0;            // 数据段数据计数指针
                    break;
                default:        // 接收到数据
                    switch(GPS_RMC_Data.Block)
                    {
                        case 0:  GPS_RMC_Data.UTCTime[GPS_RMC_Data.BlockIndex] = sbuf;  break;
                        case 1:  GPS_RMC_Data.Status = sbuf;                            break;
                        case 2:  GPS_RMC_Data.Latitude[GPS_RMC_Data.BlockIndex] = sbuf; break;
                        case 3:  GPS_RMC_Data.NS = sbuf;                                break;
                        case 4:  GPS_RMC_Data.Longitude[GPS_RMC_Data.BlockIndex] = sbuf;break;
                        case 5:  GPS_RMC_Data.EW = sbuf;                                break;
                        case 6:  GPS_RMC_Data.Speed[GPS_RMC_Data.BlockIndex] = sbuf;    break;
                        case 7:  GPS_RMC_Data.Course[GPS_RMC_Data.BlockIndex] = sbuf;   break;
                        case 8:  GPS_RMC_Data.UTCDate[GPS_RMC_Data.BlockIndex] = sbuf;  break;
                        default: break;
                    }         
                    GPS_RMC_Data.BlockIndex++;
                    break;
            }
        }while(sbuf != '*');

        memset(buf, 0x00, sizeof(buf));
        buf[0] = GPS_RMC_Data.NS;
        buf[1] = ' ';
        buf[2] = ' ';
        memcpy(buf + 3, &GPS_RMC_Data.Latitude, 9);
        LCD_ShowString(8, 20, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = GPS_RMC_Data.EW;
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Longitude, 10);
        LCD_ShowString(120, 20, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'T';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.UTCTime, 10);
        LCD_ShowString(8, 40, buf, 0);
/*
        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'S';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Speed, 5);
        LCD_ShowString(8,100, buf, 0);

        memset(buf, 0x00, sizeof(buf));
        buf[0] = 'C';
        buf[1] = ' ';
        memcpy(buf + 2, &GPS_RMC_Data.Course, 5);
        LCD_ShowString(8,120, buf, 0);
*/
    }
    return 0;
}

INT8U GPGSV_Receive(void)
{
    INT8U buf[8] = "Sat: 00";
    INT8U i, sbuf;
    INT8U *ptr;
    INT16U index;

    memset(&GPS_GSV_Data, 0x00, sizeof(GPS_GSV_Data));  // 每次处理前将结构体清零   
    index = Find_Str(Uart1_RcvBuf, "$GPGSV,");
    if(index)
    {
        ptr = Uart1_RcvBuf  + index + 6;
        do
        {
            sbuf = *ptr++;
            switch(sbuf)
            {
                case ',':
                    GPS_GSV_Data.Block++;
                    GPS_GSV_Data.BlockIndex=0;
                    break;
                default:     
                    switch(GPS_GSV_Data.Block)
                    {
                        case 1:     //当前GPFSV语句的序号, 该序号计算出该组卫星数据应该存放于数组的哪个位置
                            GPS_GSV_Data.GSVID = sbuf - '1';         
                            break;
                        case 2:
                            GPS_GSV_Data.SateInView[GPS_GSV_Data.BlockIndex] = sbuf;
                            break;
                        case 3:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].SatelliteID[GPS_GSV_Data.BlockIndex] = sbuf;
                            break;
                        case 4:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].Elevation[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 5:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].Azimuth[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 6:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].SNR[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 7:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].SatelliteID[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 8:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].Elevation[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 9:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].Azimuth[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 10:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].SNR[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 11:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].SatelliteID[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 12:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].Elevation[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 13:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].Azimuth[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 14:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].SNR[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 15:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].SatelliteID[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 16:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].Elevation[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 17:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].Azimuth[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                        case 18:
                            GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].SNR[GPS_GSV_Data.BlockIndex]=sbuf;
                            break;
                    }
                    GPS_GSV_Data.BlockIndex++;
                    break;
            }
        }while(sbuf != '*');

        for(i = 0; i < 4; i++)
        {


        }


        //memcpy(buf + 5, &GPS_GSV_Data.SateInView, 2);
        //LCD_ShowString(8, 60, buf, 0);
    }
    return 0;
}

INT8U GPGGA_Receive(void)
{
    INT8U sbuf;
    INT8U *ptr;
    INT16U index;

    memset(&GPS_GGA_Data, 0x00, sizeof(GPS_GGA_Data));  // 每次处理前将结构体清零   
    index = Find_Str(Uart1_RcvBuf, "$GPGGA,");
    if(index)
    {
        ptr = Uart1_RcvBuf  + index + 6;
        do
        {
            sbuf = *ptr++;
            switch(sbuf)
            {  
                case ',':        // 该字段结束, 下一个
                    GPS_GGA_Data.Block++;
                    GPS_GGA_Data.BlockIndex = 0;                //字段索引置0:第一个字符
                    break;
                default:        // 字段字符                        
                    switch(GPS_GGA_Data.Block)  //判断当前处于哪个字段
                    {               
                        //case 0:
                            //GPS_GGA_Data.UTCTime[GPS_GGA_Data.BlockIndex]=sbuf;
                            //break;
                        //case 1:
                            //GPS_GGA_Data.Latitude[GPS_GGA_Data.BlockIndex]=sbuf;
                            //break;
                        //case 2:
                            //GPS_GGA_Data.NS=sbuf;
                            //break;
                        //case 3:
                            //GPS_GGA_Data.Longitude[GPS_GGA_Data.BlockIndex]=sbuf;
                            //break;
                        //case 4:
                            //GPS_GGA_Data.EW=sbuf;
                            //break;
                        case 5:
                            GPS_GGA_Data.PositionFix=sbuf;
                            break;
                        case 6:
                            GPS_GGA_Data.SateUsed[GPS_GGA_Data.BlockIndex]=sbuf;
                            break;
                        //case 7:
                            //GPS_GGA_Data.HDOP[GPS_GGA_Data.BlockIndex]=sbuf;
                            //break;
                        case 8:
                            GPS_GGA_Data.Altitude[GPS_GGA_Data.BlockIndex]=sbuf;
                            break;
                    }         
                    GPS_GSV_Data.BlockIndex++;   //字段索引++, 指向下一个字符  
                    break;
            }
        }while(sbuf != '*');

    }
    return 0;
}


INT8U GPGSA_Receive(void)
{
    INT8U sbuf;
    INT8U *ptr;
    INT16U index;

    memset(&GPS_GSA_Data, 0x00, sizeof(GPS_GSA_Data));  // 每次处理前将结构体清零   
    index = Find_Str(Uart1_RcvBuf, "$GPGSA,");
    if(index)
    {
        ptr = Uart1_RcvBuf  + index + 6;
        do
        {
            sbuf = *ptr++;
            switch(sbuf)
            {
                case ',':
                    GPS_GSA_Data.Block++;
                    GPS_GSA_Data.BlockIndex=0;  
                    break;  
                default:
                    switch(GPS_GSA_Data.Block)  
                    {
                        case 0:
                            GPS_GSA_Data.Mode = sbuf;   
                            break;  
                        case 1:
                            GPS_GSA_Data.Mode2 = sbuf;
                            break;  
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 9:
                        case 10:
                        case 11:
                        case 12:
                        case 13:        //2-13 是已使用的卫星ID, 保存于数组中
                            GPS_GSA_Data.SateUsed[GPS_GSA_Data.Block-2][GPS_GSA_Data.BlockIndex]=sbuf;  
                            break;  
                        case 14:
                            GPS_GSA_Data.PDOP[GPS_GSA_Data.BlockIndex]=sbuf;
                            break;  
                        case 15:
                            GPS_GSA_Data.HDOP[GPS_GSA_Data.BlockIndex]=sbuf;
                            break;  
                        case 16:
                            GPS_GSA_Data.VDOP[GPS_GSA_Data.BlockIndex]=sbuf;
                            break;  
                    }         
                    GPS_GSV_Data.BlockIndex++;   //字段索引++, 指向下一个字符  
                    break;
            }
        }while(sbuf != '*');
    }
    return 0;
}

出0入0汤圆

发表于 2010-11-29 11:19:21 | 显示全部楼层
对于RAM不大的单片机,如果只接收部分数据包的话可按下面的
/************************************************************************
AS1_RcvState:   0 接收挂起状态 等待接收到'$'才动作
                1 接收数据头并判断 如为"$GPRMC"则为2
                2 判断成功 开始接收数据包 接收到'*'后为3
                3 接收完成 等待超时后处理 同时清0返回挂起状态等待下一次接收
*************************************************************************/
ISR(AS1_InterruptRx)
{
    byte OnFlags = 0x00;                 // Temporary variable for flags
    byte StatReg = SCIS1;                // Temporary variable for status flags
    AS1_TComData Data = SCID;            // Read data from the receiver into temporary variable for data

    //setReg8(MTIMSC, 0x10);             // 关闭定时器 Stop timer  
    setReg8(TPMSC, 0x00);                /* Stop HW; disable overflow interrupt and set prescaler to 0 */

    if (AS1_InpLen < AS1_INP_BUF_SIZE)
    {     
        if(Data == '$' && AS1_RcvState != 3)
        {
            AS1_InpLen = 0;
            AS1_RcvState = 1;
        }
        if(AS1_RcvState == 1)
        {
            AS1_InpBuffer[AS1_InpLen++] = Data;   
            if(AS1_InpLen == 6)
            {   //-------------- 这里不用比较字符串的方式 需要哪个数据包就换相关的字符
                if(AS1_InpBuffer[1] == 'G' && AS1_InpBuffer[2] == 'P' && AS1_InpBuffer[3] == 'R' \
                && AS1_InpBuffer[4] == 'M' && AS1_InpBuffer[5] == 'C')
                {
                    AS1_RcvState = 2;   
                }
                else
                {
                    AS1_RcvState = 0;       // 返回0状态等待接收
                }
            }
        }
        else if(AS1_RcvState == 2)
        {
            AS1_InpBuffer[AS1_InpLen++] = Data;  
            if(Data == '*')
            {
                //AS1_Rcvbit = 1;
                AS1_RcvState = 3;   // 状态3是为防止此次数据帧再次接收到'$'后破坏数据结构
                AS1_InpLen = 0;  
            }
        }
    }
    else
    {
        SerFlag |= FULL_RX;                // If yes then set flag buffer overflow
        OnFlags |= ON_ERROR;               // Set flag "OnError"         
    }
  /* TPMSC: TOF=0,TOIE=0,CPWMS=0,CLKSB=0,CLKSA=0,PS2=0,PS1=0,PS0=0 */
  //setReg8(TPMSC, 0x00);                /* Stop HW; disable overflow interrupt and set prescaler to 0 */
  /* TPMC0SC: CH0F=0,CH0IE=1,MS0B=0,MS0A=1,ELS0B=0,ELS0A=0,??=0,??=0 */
  //setReg8(TPMC0SC, 0x50);              /* Set output compare mode and enable compare interrupt */
  TTicks = 0;                          /* Counter of timer ticks */
  //TOvf = FALSE;                        /* Counter overflow flag */
  FC161_SetCV(0xFEFFU);                /* Inicialize appropriate value to the compare/modulo/reload register */
  setReg8(TPMCNTH, 0x00);              /* Reset HW Counter */
  setReg8(TPMSC, 0x0A);                /* Set prescaler and run counter */
  /*   
    //------- 启动定时器并重新装值等待超时溢出 32ms   
    TTicks = 0;                          // Counter of timer ticks
    // TOvf = FALSE;                     // Counter overflow flag
    FC161_SetCV(0xFE);                   // Inicialize appropriate value to the compare/modulo/reload register
    // setReg8(MTIMCLK, 0x11);           // Set clock-source and prescaler  
    setReg8(MTIMSC, 0x60);               // Reset HW Counter and run timer  
    */
}

出0入0汤圆

发表于 2010-11-29 11:22:10 | 显示全部楼层
上面是用的Freescale的单片机
这个是我改写的比较字符串的函数,注意返回的是偏移量
INT16U Find_Str(INT8U *str, INT8U *ptr)
{
        INT16U index = 0;
        INT8U *s_temp;      
        INT8U *m_temp;      
        INT8U *t_temp;
            
        if(str == 0 || ptr == 0)
            return 0;
        for(s_temp = str; *s_temp != '\0'; s_temp++)
        {
                index++;
                m_temp = s_temp;
                for(t_temp = ptr; *t_temp == *m_temp; t_temp++, m_temp++){  };
                if(*t_temp == '\0')
                        return index;
        }
        return 0;
}

出0入0汤圆

发表于 2010-11-29 11:43:41 | 显示全部楼层
第一种可能大家不屑,但对于通信间隔不定的话还是比较实用,因为超时也不一定见效
第二种是环链型处理的,可能某些场合适用
第三种的话比较常用,但如果从机(主机)有应答的话,可不用定时器,加几十ms延时就OK

出0入0汤圆

发表于 2010-12-9 17:25:08 | 显示全部楼层
学习学习

出0入0汤圆

发表于 2010-12-9 17:34:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-9 18:31:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-13 21:07:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-2 11:51:28 | 显示全部楼层
好,太强了!做个记号!

出0入0汤圆

发表于 2011-3-2 12:12:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-2 13:40:28 | 显示全部楼层
单片机串口接收数据的一点建议:对于有格式需要判断包头包尾的数据包,一定要做个接收超时处理,不然一个包出错,可能将导致以后所有的包全都收不到。

出0入0汤圆

发表于 2011-4-14 11:43:47 | 显示全部楼层
正好有相关的问题,学习了,非常感谢分享

出0入0汤圆

发表于 2011-4-14 14:46:03 | 显示全部楼层
不错啊

出0入0汤圆

发表于 2011-4-14 15:52:28 | 显示全部楼层
记号

出0入0汤圆

发表于 2011-4-15 23:45:18 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-4-16 00:07:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-18 23:33:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-12 00:36:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-12 12:01:29 | 显示全部楼层
回复【楼主位】renjun861214
-----------------------------------------------------------------------

可以这样,把所有数据接收到缓存数组里(这样中断函数里程序很少),然后根据调度器再写个处理函数定时检查缓存数组里的数据就ok了吧~
void Tx_Rx_0_Update(void) interrupt INTERRUPT_UART_0_Rx_Tx
{
        if(RI0)
        {
                RI0 = 0;//清中断标志
                UART0_Rx_Buffer[UART0_Rx_Buffer_In++]= SBUF0;//接收数据
                if(UART0_Rx_Buffer_In == UART0_Rx_Buffer_MAX)//循环数组,如果数据量又大又快,可以把数组定义大一些。
                {
                        UART0_Rx_Buffer_In = 0;
                }
        }
        if(TI0)
        {
                if(UART0_Tx_Buffer_Out != UART0_Tx_Buffer_In)//首尾不相等,这个数组也要定义大些,使cpu能处理过来,保证不溢出
                {
                        SBUF0 = UART0_Tx_Buffer[UART0_Tx_Buffer_Out++];//发送数组数据
                        if(UART0_Tx_Buffer_Out == UART0_Tx_Buffer_MAX)//循环数组
                        {
                                UART0_Tx_Buffer_Out = 0;
                        }
                }
                else
                {
                        TI0 = 0;//关中断标志
                }
        }
}
数据都写在数组里,想发送的时候TI0 = 1;就ok了

出0入0汤圆

发表于 2011-5-27 10:54:19 | 显示全部楼层
学习了呵呵

出0入0汤圆

发表于 2011-6-16 19:19:24 | 显示全部楼层
谢谢..学习了

出0入0汤圆

发表于 2011-6-28 09:57:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-1 17:50:36 | 显示全部楼层
很好,看到了那个双串口
支持双串口的77E58程序

#include <W77E58.h>
#include <Const.h>
#include <CRC8.h>

bit fSeri0_Send_Ok;
bit fSeri1_Send_Ok;

bit fSeri1_Odd;

/**************************************************
串口0队列
**************************************************/
unsigned char xdata xBuf_Send_0[XBUFSERIAL0SEND];
unsigned char xdata xBuf_Reci_0[XBUFSERIAL0RECI];

unsigned char xdata *Seri0_ReadSendPoint=xBuf_Send_0;
unsigned char xdata *Seri0_WriteSendPoint=xBuf_Send_0;
unsigned char data Seri0_SendNum;

unsigned char xdata *Seri0_ReadReciPoint=xBuf_Reci_0;
unsigned char xdata *Seri0_WriteReciPoint=xBuf_Reci_0;
unsigned int data Seri0_ReciNum;

/**************************************************
压入单数据串口0发送队列
**************************************************/
void Seri0_PushSend(unsigned char mData)
{
*Seri0_WriteSendPoint=mData;
if(Seri0_WriteSendPoint==(xBuf_Send_0+XBUFSERIAL0SEND-1))
Seri0_WriteSendPoint=xBuf_Send_0;
else Seri0_WriteSendPoint++;
Seri0_SendNum++;
if(fSeri0_Send_Ok==0){fSeri0_Send_Ok=1;TI=1;}
}

/**************************************************
弹出串口0接收队列单数据
**************************************************/
unsigned char Seri0_PopReci()
{
unsigned char i;
i=*Seri0_ReadReciPoint;
if(Seri0_ReadReciPoint==(xBuf_Reci_0+XBUFSERIAL0RECI-1))
Seri0_ReadReciPoint=xBuf_Reci_0;
else Seri0_ReadReciPoint++;
Seri0_ReciNum--;
return i;
}

/**************************************************
读出串口0接收队列指定序号数据
**************************************************/
unsigned char Seri0_ReadReci(unsigned char mId)
{
unsigned char xdata *pTemp;
pTemp=Seri0_ReadReciPoint+mId;

if(pTemp<(xBuf_Reci_0+XBUFSERIAL0RECI))return(*pTemp);
else return(*(pTemp-XBUFSERIAL0RECI));
}


/**************************************************
串口1队列
**************************************************/
unsigned char xdata xBuf_Send_1[XBUFSERIAL1SEND];
unsigned char xdata xBuf_Reci_1[XBUFSERIAL1RECI];

unsigned char xdata *Seri1_ReadSendPoint=xBuf_Send_1;
unsigned char xdata *Seri1_WriteSendPoint=xBuf_Send_1;
unsigned int data Seri1_SendNum;

unsigned char xdata *Seri1_ReadReciPoint=xBuf_Reci_1;
unsigned char xdata *Seri1_WriteReciPoint=xBuf_Reci_1;
unsigned char data Seri1_ReciNum;

/**************************************************
压入单数据串口1发送队列
**************************************************/
void Seri1_PushSend(unsigned char mData)
{
*Seri1_WriteSendPoint=mData;
if(Seri1_WriteSendPoint==(xBuf_Send_1+XBUFSERIAL1SEND-1)){
Seri1_WriteSendPoint=xBuf_Send_1;
}
else Seri1_WriteSendPoint++;
Seri1_SendNum++;
if(fSeri1_Send_Ok==0){fSeri1_Send_Ok=1;TI_1=1;}
}

/**************************************************
弹出串口1接收队列单数据
**************************************************/
unsigned char Seri1_PopReci()
{
unsigned char i;
i=*Seri1_ReadReciPoint;
if(Seri1_ReadReciPoint==(xBuf_Reci_1+XBUFSERIAL1RECI-1))
Seri1_ReadReciPoint=xBuf_Reci_1;
else Seri1_ReadReciPoint++;
Seri1_ReciNum--;
return i;
}


/**************************************************
CY=0,使用T1;CY=1,使用T2
入口:Location=0,串口0;否则串口1
mBps,波特率。参考Const.h中的定义
mMode,方式。2慰糃onst.h中的定义
**************************************************/
void Init_Serial(unsigned char Location,unsigned char mBps,unsigned char mMode)
{
if(CY==0){ /*T1*/
TMOD=(TMOD&0x0f)|0x20; /*自动重装*/
if(Location){ /*second*/
ACC=mBps;
if(ACC7)CKCON|=0x20; /*x3*/
ACC=mBps;
if(ACC6)WDCON|=0x80; /*x2*/
}
else {
/*first*/
ACC=mBps;
if(ACC7)CKCON|=0x10; /*x3*/
ACC=mBps;
if(ACC6)PCON|=0x80; /*x2*/
}
mBps&=0x3f;
TL1=TH1=(~mBps)+1;
TR1=1;
}
else
{
/*T2*/
ACC=mBps;
if(ACC7)CKCON|=0x40; /*x3*/
ACC=mBps;
if(ACC6==0)mBps<<=1; /*x2*/
mBps&=0x3f;

mBps*=6;

TL2= RCAP2L=(~mBps)+1;
TH2=RCAP2H=0xff;
T2CON|=0x30; /*选择T2为波特率发生器*/
TR2=1;
}

if(Location==0){
SCON|=0x40; /*方式8位*/
REN=1;
ES=1;
}
else {
ACC=mMode;
if(ACC3){
SCON1|=0xc0; /*方式9位*/
}
else {
SCON1|=0x40; /*方式8位*/
}
fSeri1_Odd=ACC4; /*奇偶效验方式,0奇*/

REN_1=1;
ES1=1;
}
}

/**************************************************
串口0中断
**************************************************/
void Int_serial0() interrupt 4 using 1{
// ES=0; /*关
串行口中断*/
if(TI){
TI = 0; /*清
发送中断标志*/
if(Seri0_SendNum==0)fSeri0_Send_Ok=0; /*已发送完毕*/
else {
SBUF=*Seri0_ReadSendPoint;

if(Seri0_ReadSendPoint==(xBuf_Send_0+XBUFSERIAL0SEND-1))
Seri0_ReadSendPoint=xBuf_Send_0;
else Seri0_ReadSendPoint++;
Seri0_SendNum--;
}
}

if(RI){
RI = 0;
*Seri0_WriteReciPoint=SBUF;
if(Seri0_WriteReciPoint==(xBuf_Reci_0+XBUFSERIAL0RECI-1))
Seri0_WriteReciPoint=xBuf_Reci_0;
else Seri0_WriteReciPoint++;
Seri0_ReciNum++;
}

// ES=1; /*开
中断*/
}

/**************************************************
串口1中断
**************************************************/
void Int_serial1() interrupt 7 using 1{
// ES1=0; /*关
串行口中断*/
if(TI_1){
TI_1 = 0; /*清
发送中断标志*/

if(Seri1_SendNum==0)fSeri1_Send_Ok=0; /*已发送完毕*/
else {
if((SCON1&0xc0)==0xc0){
ACC=*Seri1_ReadSendPoint;
if(fSeri1_Odd==0)TB8=~P; /*奇效验*/
else TB8=P;
/*偶效验*/
}

SBUF1=*Seri1_ReadSendPoint;
if(Seri1_ReadSendPoint==(xBuf_Send_1+XBUFSERIAL1SEND-1))
Seri1_ReadSendPoint=xBuf_Send_1;
else Seri1_ReadSendPoint++;
Seri1_SendNum--;
}
// SBUF1=0xaa;
}

if(RI_1){
RI_1 = 0;
*Seri1_WriteReciPoint=SBUF1;
if(Seri1_WriteReciPoint==(xBuf_Reci_1+XBUFSERIAL1RECI-1))
Seri1_WriteReciPoint=xBuf_Reci_1;
else Seri1_WriteReciPoint++;
Seri1_ReciNum++;
}

// ES1=1;
/*开中断*/
}
/***********************************************************
串口1打包程序
***********************************************************/
void Seri1_Block()
{
unsigned char i,j;

if(Seri1_ReciNum==0)return;

/*包*/
if(Seri1_ReciNum>BLOCKMAX)i=BLOCKMAX;
else i=Seri1_ReciNum;

/*--------------------------------------*/
Seri0_PushSend(STX);
Crc8_ClrSum();
Seri0_PushSend(SERIAL1);
Crc8_AddSum(SERIAL1);
Seri0_PushSend(i);
Crc8_AddSum(i);

while(i>0){
j=Seri1_PopReci();
Seri0_PushSend(j);
Crc8_AddSum(j);
i--;
}

Seri0_PushSend(Crc8_GetSum());
Seri0_PushSend(ETX);
}

//Const.h
#define STX 0x02
#define ETX 0x03
#define BLOCKMAX 50

#define NONEPARITY 0x0
#define ODDPARITY 0x08
#define EVENPARITY 0x18
#define DATA7BIT 0x80

#define LOCAL 0
#define SERIAL1 1
#define SERIAL5540 2
#define SERIAL5541 3
#define SERIAL5542 4
#define SERIAL5543 5
#define SERIAL25540 6
#define SERIAL25541 7
#define SERIAL25542 8
#define SERIAL25543 9


#define RIGHT 1
#define ERROR 2

/*th=256-2^n*f/384/B*/
#define BPS115200_22M 1|0x40
#define BPS57600_22M 1
#define BPS38400_22M 3|0x40
#define BPS19200_22M 3
#define BPS9600_22M 6
#define BPS4800_22M 12
#define BPS2400_22M 24
#define BPS1200_22M 48

//#define BPS115200_30M_77E58 4|0x80 /**3*/
//#define BPS57600_30M_77E58 8|0x80 /**3*/
//#define BPS38400_30M_77E58 2
//#define BPS19200_30M_77E58 4
//#define BPS9600_30M_77E58 8
//#define BPS4800_30M_77E58 16
//#define BPS2400_30M_77E58 32

#define XBUFSERIAL0SEND 250
#define XBUFSERIAL0RECI 2000

#define XBUFSERIAL1SEND 1800
#define XBUFSERIAL1RECI 100

#define XBUFSERIAL554RECI 186


sbit ACC0=ACC^0;
sbit ACC1=ACC^1;
sbit ACC2=ACC^2;
sbit ACC3=ACC^3;
sbit ACC4=ACC^4;
sbit ACC5=ACC^5;
sbit ACC6=ACC^6;
sbit ACC7=ACC^7;

//调用
/*初始化内部串行口,0=115200X8,1=9600*9*/
Serial0_Init
(); /*使用T2*/
CY=0;Init_Serial(1,BPS38400_22M,NONEPARITY); /*printer,使用T1*/

出0入0汤圆

发表于 2011-7-13 00:14:39 | 显示全部楼层
正好要用……谢谢

出0入0汤圆

发表于 2011-7-25 14:39:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-30 14:09:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-4 09:42:14 | 显示全部楼层
小弟最近也遇到一个串口接收数据包的的问题,通信用的是ISO14443A的通信协议
W 02    向下位机发送(包头)
R 10     接收
W 18 41 01 00 58 10 03  (18为一随机数,41为命令,01为数据长度且数据长度不固定,03为包尾)
R 10     接收
当上位机发送02时,等待下位机响应10,如果不响应10则不发送后面的数据。各位大侠帮帮忙哈。

出0入0汤圆

发表于 2011-8-5 15:56:58 | 显示全部楼层
咋没人响应呢

出0入0汤圆

发表于 2011-9-14 21:50:42 | 显示全部楼层
我也是初学51单片机,最近想做一个串口通信工装,我主要是用串口接收对方单片机发送过来的数据用5位自带译码驱动的8421数码管显示出来,这是对方发送的一次数据01 01 01 34 35 32 36 37 32 34 31.......,由于刚学所以对把数据取出来如何让个、十、百、千、万将5个数据显示出来,刚看了很多老师的程序感到学到很多,很多是书上看不到的,先感谢各位老师的指点。

出0入0汤圆

发表于 2011-11-3 14:26:25 | 显示全部楼层
感谢LS各位高手,小弟学习了

出0入0汤圆

发表于 2011-12-14 20:54:13 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-15 14:56:15 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-12-15 15:10:29 | 显示全部楼层
用软件FIFO吧。

出0入0汤圆

发表于 2011-12-15 16:52:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-21 16:04:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-21 16:27:58 | 显示全部楼层
回复【17楼】728196 彳亍者
mark
-----------------------------------------------------------------------

出0入0汤圆

发表于 2011-12-22 18:38:33 | 显示全部楼层
大段大段的代码...

出0入0汤圆

发表于 2012-3-5 20:58:57 | 显示全部楼层
bucuo

出0入0汤圆

发表于 2012-3-6 16:54:42 | 显示全部楼层
mark

出75入4汤圆

发表于 2012-9-2 10:33:35 | 显示全部楼层
这个通信程序不错

出0入0汤圆

发表于 2012-9-3 10:26:21 | 显示全部楼层
好!!!

出0入0汤圆

发表于 2012-9-3 10:39:03 | 显示全部楼层
mark 。。。。

出0入0汤圆

发表于 2012-9-3 12:00:16 | 显示全部楼层
mark!!!!

出0入0汤圆

发表于 2012-9-29 16:50:43 | 显示全部楼层
串口超时

出0入0汤圆

发表于 2012-11-6 21:57:16 | 显示全部楼层
再顶一下,现在做触摸屏与单片机通讯,正需要。。。。。。

出0入0汤圆

发表于 2013-11-5 15:14:27 | 显示全部楼层
这个挺有用。

出0入0汤圆

发表于 2014-7-15 13:24:44 | 显示全部楼层
amazing030 发表于 2010-4-12 17:43
接收计数i要定义成全局或静态变量,而且你这样写包头包尾没起作用,临时写一段,接收计数你测试时注意下, ...

不知道2个单片机可不可以这样做呢?
假设主机和多个从机之间就是这样通讯
主机发出一个地址码+指令码+效验

从机在中断里面根据地址码判断是不是和自己的匹配,如果是,那么判断指令码,然后返回数据给主机。
我有一个疑问,就是返回给主机的数据,是在中断里去读取呢,还是查询?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 03:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表