串口通讯,2字节可以,多了就不行了。(已经解决了)

2020-01-27 11:43发布

本帖最后由 硅谷狂夫 于 2013-6-13 22:16 编辑

用串口助手发2字节,返回正常,LCD也显示正常,但发3字节就只显示和返回前2字节的内容。多发送1次,就显示前一次的最后1字节和第2次的前2个字节。各位帮忙看看问题出在哪里?



#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar flag,i,xms,zi,num;
sbit lcdrs=P3^4;                         //液晶写命令/数据控制端。
sbit lcdrw=P3^5;
sbit lcden=P3^7;                         //液晶势能端。
//uchar code table[]="OK";
unsigned char table1[3]={0,0,0};

void delayms(uint xms)
{       
        uint i,j;
        for(i=xms;i>0;i--)
                for(j=110;j>0;j--);
}

void init()
{
        TMOD=0x20;           //设置T1定时器为工作方式2,8位初值自动重装的8位定时器。
        TH1=0xf3;                //TH1初装值。晶振为12M,波特率只能为2400,这样误差最小
        TL1=0xf3;                //TL1初装值。 波特率为2400
        TR1=1;                        //启动定时器1.
        REN=1;                   //把串口接受设置为允许。
        //PCON=0x80; //把SMOD置1,波特率加1倍。为19200
        SM0=0;                   //设置串口为工作方式1,10位异步收发(8位数据),
        SM1=1;                  // 波特率可变,由定时器T1的溢出率控制。
        EA=1;                  //开总中断。
        ES=1;                  //开串口中断。
}

void write_com(uchar com)             //1602液晶写指令。
{
        lcdrs=0;
        P2=com;
        delayms(5);
        lcden=1;
        delayms(5);
        lcden=0;
}

void write_data(uchar date)           //1602液晶写数据
{
        lcdrs=1;
        P2=date;
        delayms(5);
        lcden=1;
        delayms(5);
        lcden=0;
}

void lcd_init()                                           //液晶初始化
{
        lcdrw=0;
        lcden=0;
        write_com(0x38);                //写指令,设置1602为16X2显示,5x7点阵,8位数据接口。
        write_com(0x0c);                //写指令,设置开显示,不显示光标。
        write_com(0x06);                //写1个字节后地址指针自动加1.
        write_com(0x01);                //显示清0,数据指针清0.
    write_com(0x80);                //定位1602数据指针到0X08
}

void main()                   //主函数
{
        init();                         //初始化
        lcd_init();
        while(1)
        {
                if(flag==1)           //判断flag是否等于1(等于1说明发生过串口中断了),
                {
                        ES=0;                //把串口中断关闭。
                        for(i=0;i<3;i++)        //循环发送table定义的数据。
                        {
                                SBUF=table1;          //从0开始,共11位。
                                while(!TI);                  //等待发送完毕TI等于1,当TI等于1时跳出while语句,否则一直循环while语句。
                        }
                        for(num=0;num<3;num++)
                        {
                                write_data(table1[num]);
                        }
                        ES=1;                                //开串口总段,
                        TI=0;                         //
                        flag=0;                                //把flag清0.
                }
        }
}
void ser() interrupt 4                 //串口中断程序。
{
                                           //把RI清0.中断申请位。
        if(RI==1){
        table1[zi]=SBUF;                                  
        zi++;
        if(zi==3)
        {
                flag=1;
                zi=0;
        }                                 
        RI=0;
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
Excellence
1楼-- · 2020-01-27 15:57
好久不用51了。
提点建议:
1,unsigned char table1[3]定义大一点,发一大串,看串口助手能否收到?
2,串口协议好好弄,帧头,命令,字节长度,字节 ,。。。校验,帧尾。
3,单步执行看看,KEIL有软件模拟串口,调试快。
Excellence
2楼-- · 2020-01-27 21:50
好久不用51了。
提点建议:
1,unsigned char table1[3]定义大一点,发一大串,看串口助手能否收到?
2,串口协议好好弄,帧头,命令,字节长度,字节 ,。。。校验,帧尾。
3,单步执行看看,KEIL有软件模拟串口,调试快。
lcw_swust
3楼-- · 2020-01-28 01:23
因为ES=0;把接收中断给关了
skynet
4楼-- · 2020-01-28 04:54
 精彩回答 2  元偷偷看……
硅谷狂夫
5楼-- · 2020-01-28 09:24
ballack_linux 发表于 2013-6-13 21:53
每次发送完一个字节要将TI置为0
上面的代码    for(i=0;i

非常感谢你的回答,以后我会尽量少贴代码。
benqme
6楼-- · 2020-01-28 12:50
学习没事顶一下

一周热门 更多>