PC机发送ABCD给单片机串口1接收到数据后由串口2转发给PC机得到的是ABC。这是为何?

2019-03-24 17:26发布

PC机发送ABCD给单片机串口1接收到数据后由串口2转发给PC机得到的是ABC。是不是数据丢失啦,,处理接收的速度比处理数据的速度要快才不会出现丢失数据的情况(这样要怎么该程序呢)单片机通过串口一接收数据,通过定时器中断来判断是否接收数据完毕,,接收任意字节的数据
/************************************************

* 芯    片     : STC12C5A60S2
* 时    钟  :11.0592MHz
* 开发环境  :Keil uVision V4.00a
* 备    注  :
  */
//文件包含
#include "stc12c5a60s2.h"

unsigned char receive_number[]={0};//接收串口发送来的数据的数组
unsigned char  rec1_count=0;//串口1接收计数器
unsigned int  rec1_flag=0; //串口1接收标志位

//全局变量
unsigned int p_send=0;
unsigned char ser_receive;  //串口1接收到的数据
unsigned char flag1,flag2,temp1,temp2,temp3,k,h,i=0;
//函数声明
void Uart2_Init(void);        //串口初始化
void Timer0_Init();      //定时器0初始化
void Uart2_SendChar(unsigned char Udat);
void Uart2_SendString(unsigned char *PBuf,unsigned char a);
void UART_1SendOneByte(unsigned char c);
void UART_1Sendstr(unsigned char *s,unsigned char b);
void Display_Menu(void);

void delayms(unsigned int n)  ///1毫秒
{
   unsigned int i;
  while(n--)
  {
      for ( i=0;i<113;i++ );
  }
}

//定时器0初始化
void Timer0_Init()  //0微秒@11.0592MHz//定时器0 工作方式2
{
AUXR |= 0x80;  //定时器时钟1T模式
TMOD &= 0xF0;  //设置定时器模式
TMOD |= 0x02;  //设置定时器模 TMOD=0x01;
TL0 = 0x00;  //设置定时初值
TH0 = 0x00;  //设置定时重载值
TF0 = 0;  //清除TF0标志
TR0 = 0;  //定时器0开始计时
ET0=1;
    EA=1;
}
///
/***********************************************
函数名称:Uart2_Init
功    能:串口2初始化函数
入口参数:无
返 回 值:无
备    注:STC12C5A60S2单片机串口2
          只能选择独立的波特率发生器,
    不能使用定时器1做为波特率发生器
************************************************/
void UartInit(void)  [url=]//115200bps@11.0592MHz[/url]
{
PCON &= 0x7F;  //波特率不倍速
SCON = 0x50;  //8位数据,可变波特率
AUXR |= 0x40;  //定时器1时钟为Fosc,即1T
AUXR &= 0xFE;  //串口1选择定时器1为波特率发生器
TMOD &= 0x0F;  //清除定时器1模式位
TMOD |= 0x20;  //设定定时器1为8位自动重装方式
//TL1 = 0x00;  //设定定时初值
    //TH1 = 0x00;  //设定定时器重装值
TL1 = 0xFD;  //设定定时初值
TH1 = 0xFD;  //设定定时器重装值
ET1 = 0;  //禁止定时器1中断
TR1 = 1;  //启动定时器1
REN=1; //允许串口接收
ES=1;  //开串口 中断
    EA=1;
//// S2BUF
AUXR &= 0xF7;  //波特率不倍速
S2CON = 0x50;  //8位数据,可变波特率
AUXR |= 0x04;  //独立波特率发生器时钟为Fosc,即1T
BRT = 0xFD;  //设定独立波特率发生器重装值
AUXR |= 0x10;  //启动独立波特率发生器
IE2=0x01;    //允许串口2中断
}
//////////////
/****************串行口1发送****************/
void UART_1SendOneByte(unsigned char c)
{  
    SBUF = c;
    while(!TI);    //若TI=0,在此等待
    TI = 0;  
}
void UART_1Sendstr(unsigned char *s,unsigned char b)
{
  while(b)   // 表示字符串结束标志,通过检测字符串末尾
{
  UART_1SendOneByte(*s); //发送一个字符
  s++;//移动到下一个字符
  b--;
}
}
/////////////
/***********************************************
*函数名称:Uart2_SendChar
*功    能:串口2发送单个字符函数
*入口参数:Udat:欲发送的数据
*返 回 值:无
*备    注:无
************************************************/
void Uart2_SendChar(unsigned char Udat)
{  ES=0;
S2BUF=Udat;    //将数据放入发送缓冲区
while(!(S2CON&0x02)); //等待发送完成
    S2CON=S2CON & 0xfd;     //清零S2TI  
ES=1;
}
/***********************************************
*函数名称:Uart2_SendString
*功    能:串口发送字符串函数
*入口参数:*PBuf:指向字符串的指针            
*返 回 值:无
*备    注:串口发送时需禁止全局中断,防止出错
************************************************/
void Uart2_SendString(unsigned char *PBuf,unsigned char a)
{
    ES=0;      //关闭中断,防止对发送缓冲区影响
    while(a)      //未到字符串末尾
    {
      Uart2_SendChar(*PBuf);
    PBuf++;
  a--;
    }
    ES=1;
}
/////////
/************串行口1中断处理函数*************/
void UART_1Interrupt(void) interrupt 4
{   
    if(RI==1)
        {
                RI = 0;
                //定时器从0开始计数
                // TF1=0;
                //开定时器,定时器开始计数
       TR0=1;
       TH0= 0x00;
                TL0= 0x00;
                if(SBUF!=0xff)//接收数据
                {   
      receive_number[rec1_count++]=SBUF;

                }

        }
}
/*******************串行口2中断处理函数*****************************/
void Uart2_ISR(void) interrupt 8
{

if(S2CON&0x01)        //发送和接收共用一个中断向量,需在程序中判断
{
  S2CON=S2CON & 0xfe;         //串口接收中断标记需软件清零
}
}

void Timer0_Rountine(void) interrupt 1 //定时器0 工作方式2
{

   rec1_flag=1; ////当定时器0溢出中断时让rec1_flag=1。

}
    //主函数
void main(void)
{

  unsigned char j;
  UartInit();     //串口2初始化
Timer0_Init();      //定时器0初始化
delayms(20);
  while(1)
{

     if(rec1_flag==1 )      //如果是1
            {     
     ES=0;
                 rec1_flag=0;      
                TR0=0;      

                 while(p_send<=rec1_count)//判断发送指针的值是否小于全局计数器
                 {        //如果是

                    Uart2_SendChar(receive_number[p_send]);//开始发送数据
                    p_send=p_send+1;   

                 }

     p_send=0; rec1_count=0;
                 ES=1;
                                   //如果不是
                                    //停止发送数据
             }                       //开串口1中断


  }

}

此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
hljjxzhla
1楼-- · 2019-03-24 22:00
beyondvv
2楼-- · 2019-03-24 22:46
串口1接受中断里面最好不要用定时器
幻听你的温柔
3楼-- · 2019-03-25 00:03
 精彩回答 2  元偷偷看……
幻听你的温柔
4楼-- · 2019-03-25 04:33
beyondvv 发表于 2016-11-14 10:39
串口1接受中断里面最好不要用定时器

哦,,那怎么办啊
zl2168
5楼-- · 2019-03-25 04:43
本帖最后由 zl2168 于 2016-11-18 20:00 编辑

实验16  单片机与PC机虚拟串行通信


虚拟串行通信说明   

添加虚拟串口   

下载“串口调试助手”   

电路设计   

程序设计   

Keil调试   

Proteus仿真   

Proteus仿真一下,确认有效。 实验16 与PC机虚拟串行通信.rar (151.41 KB, 下载次数: 4) 2016-11-18 19:59 上传 点击文件名下载附件 pc.jpg 以上摘自张志良编著80C51单片机实用教程》ISBN978-7-04-044532-9,高教社出版。     书中电路和程序设计有详细说明,程序语句条条有注解。

一周热门 更多>