打印

51模拟串口

[复制链接]
663|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
llljh|  楼主 | 2015-8-15 17:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

sbit BT_RXD=P3^2;                       //接收
sbit BT_TXD=P1^5;                       //发送

sbit AP_EN=P1^4;                        //射频使能

sbit RS=P0^0;
sbit RW=P0^1;
sbit E=P0^2;
sbit BF=P2^7;

#define uchar  unsigned char
#define uint unsigned int
#define SomeNop();{_nop_();_nop_();}
#define Rec_Byte 16                     //最大接收字节
#define T0_Enable() {TL0=TH0;TR0=1;fT0out=0;}                 //定时器T0打开
#define T0_Disable() {TR0=0;fT0out=0;}                        //关定时器T0
#define T0_Wait() {while(!fT0out);fT0out=0;}                  //等待定时器溢出,时间到1/9600秒

unsigned char fT0out=0;                 //超出溢出标志位,时间到1/9600秒
unsigned char RecData[16];              //接收数据缓存区
unsigned char RecCount=0;               //接收数据计数器
unsigned int fstart=0;                  //起始位标志

unsigned int  fdisplay ;//显示标志
unsigned char DataAlarm ;//报警位
unsigned char DataH         ;        //数据高 8位
unsigned char DataL         ;        //数据低 8位
unsigned char TempH         ;        // 温度高8位
unsigned char TempL         ;        // 温度低8位
unsigned char DataCRC ;        //        校验位
unsigned int falarm ;//报警标志

unsigned char code mun_to_char[]={"0123456789"};

/*函数功能:延时1ms*/
void delay1ms()
  {
    unsigned char i,j;
          for(i=0;i<10;i++)
           for(j=0;j<33;j++)
            ;
  }
/*函数功能:延时若干秒,入口参数:n*/
void delay (unsigned char n)
  {
  unsigned char i;
   for (i=0;i<n;i++)
      delay1ms();
  }
  /*函数功能:判断液晶模块的忙碌状态*/
unsigned char BusyTest(void)
{
   unsigned char result;
   P2 = 0XFF;
   E=0;
   RS=0;
   RW=1;
   SomeNop();
   E=1;
   SomeNop();
   result=(P2&0x80);
   E=0;
   return result;
}
/*函数功能:将模式指令或显示地址写入液晶模块*/
void WriteInstruction (unsigned char dictate)
{
   while(BusyTest()!=0);
   RS=0;
   RW=0;
   E=0;
   SomeNop();
   E=1;
   P2=dictate;
   SomeNop();
   SomeNop();
   E=0;
}
/*函数功能:显示位置确定*/
void LCD_CoordinateXY(unsigned char X, unsigned char Y)
  {
    X &= 0x1f;                          // X位置范围 0~23
    Y &= 0x01;                          // Y位置范围 0~ 1
    if(Y == 0)                          //数据在第一行显示
    {
     WriteInstruction( X|0x80 );
    }
   else if(Y == 1)                      //数据在第二行显示
    {
     WriteInstruction( (X+0x40)|0x80 );
    }
  }
/*函数功能:将数剧写入液晶模块,入口参数:sum(字符常量)*/
void WriteData(unsigned char sum)
{
   while(BusyTest()!=0);
   RS=1;
   RW=0;
   E=0;

   _nop_();
   _nop_();
   _nop_();
   _nop_();

   E=1;
   _nop_();
   _nop_();
   P2=sum;
   _nop_();
   _nop_();
   E=0;
}
/*函数功能:LCD液晶模块初始化设置*/
void LcdInitiate(void)
{
   delay(16);
   WriteInstruction(0x38);                                //FUNCTION  SET
   delay(5);
   WriteInstruction(0x38);                                //FUNCTION  SET
   delay(5);
   WriteInstruction(0x38);                                //FUNCTION  SET
   delay(5);
   WriteInstruction(0x38);                                //FUNCTION  SET
   delay(5);
   WriteInstruction(0x08);                                //DISPLAY OFF
   delay(5);
   WriteInstruction(0x01);                                //DISPLAY CLEAR
   delay(5);
   WriteInstruction(0x0C);              //DISPLAY ON/OFF设置,光标不显示
   delay(5);
   WriteInstruction(0x06);              //ENTER MODE SET
   delay(5);
}

/*发送单个字节*/
void SendByte(unsigned char b)
{
        unsigned char i=8;
        TXD=0;                              //起始位0
        T0_Enable();
        T0_Wait();
        while(i--)
        {
                if(b&1) {BT_TXD=1;}                //相同就发送1
                else    {BT_TXD=0;}                //不同就发送0
                T0_Wait();
                b>>=1;                          //先发最低位,在来一个数据右移1位
        }
        TXD=1;                              //结束位1
        T0_Wait();
        T0_Disable();        
}
/*接收一个字节*/
unsigned char RecByte(void)
{
        unsigned char i=0;
        unsigned char b=0;
        T0_Enable();
    T0_Wait();
/*    while(i<8)
    {
            b>>=1;
            if(BT_RXD) b|=0x80;
            i++;
            T0_Wait();            
    }*/
    for(i=0;i<8;i++)
    {
            if(RXD)b|=(1<<i);
            T0_Wait();
    }
    T0_Wait();
        T0_Disable();                       //接完一个字节数据
    fstart=0;                           //起始位清零,准备接受下一个字节
    EX0=1;                              //一个字节收完后,开外部中断
//    RecData[RecCount]=b;              //把收到的数据放到准备好的数组里
//   RecCount++;
//    if(RecCount>=Rec_Byte)
//        {
//                RecCount=0;
//        }                                   //超过数组缓存,数组计数清零
        return b;
}
/*外部中断0,对起始位进行监控*/
void StartBit(void) interrupt 0
{
//        TR0=1;
//        T0_Wait();
        fstart=1;
    EX0=0;               
}
/*外部中断0初始化*/
void Start_init()
{
        EA=1;
        EX0=1;
        IT0=1;        
}
/*定时器初始化,计数方式2*/
void T0_init(void)
{   
    /*if(fstart==0)
        {
        TMOD=0x02;
            TR0=0;
            TF0=0;
                TH0=(256-48);                   //第一次下降沿是采用1/19200秒进行计数  
                TL0=TH0;                        
                ET0=1;
                EA=1;
    }*/        
//    else if(fstart==1)
//        {
        TMOD=0x02;
            TR0=0;
            TF0=0;
                TH0=(256-99);   
                TL0=TH0;                         //有下降沿时,开始1/9600秒进行计数
//            if(fstart==0) TL0=TH0=(256-49);                     //还未查询到下降沿是采用1/19200秒进行计数
//            else if(fstart==1) TL0=TH0=(256-99);                //有下降沿时,开始1/9600秒进行计数
                ET0=1;
                EA=1;
//   }        
}

/*定时器T0中断*/
void T0_int() interrupt 1
{
        fT0out=1;
//        EX0=0;                              //第一次进入定时器中断后,关外部中断
}
/*解析数据*/
void Jiexishuju(void)
{
    unsigned int i;
    if(RecCount>=8)
          {
        if((RecData[0]==0x68)&&(RecData[1]==0xaa))
              {
                   DataAlarm=RecData[2];
                         DataH=RecData[3];
                     DataL=RecData[4];
                         TempH=RecData[5];
                         TempL=RecData[6];
                         DataCRC=RecData[7];
                         RecData[7]=0;
                         for(i=8;i>1;i--)
                         {
                                 RecData[7]+=RecData[i];
                         }
                     if(DataCRC==RecData[7])
                         {
                                 fdisplay=1;
                         }                                                                        
                }        
    }
    RecCount=0;
}
/*液晶显示*/
void Display()
{
    LCD_CoordinateXY(0,0);
        WriteData(mun_to_char[DataH/10]);
    LCD_CoordinateXY(1,0);
        WriteData(mun_to_char[DataH%10]);
}

/*主函数*/
void main (void)
{
//        unsigned char i;
    AP_EN=1;
        LcdInitiate();                      //LCD2402 初始化
        delay(50);
        WriteInstruction(0x01);             //确定写位置
        delay(50);
    T0_init();                          //TO定时器初始化
        delay(10);
        Start_init();                       //判断起始位外部中断初始化
        delay(10);
        
        while(1)
        {
                if(fstart==1)
                {
                        RecData[RecCount]=RecByte();                     //把收到的数据放到准备好的数组里
                    RecCount++;
                    if(RecCount>=Rec_Byte)
                        {
                                RecCount=0;
                        
                 
                        Jiexishuju();
                        }
                }
                if(fdisplay==1)
        {
            Display();
        }

//                                                for(i=0;i<Rec_Byte;i++)
//                                                        {
//                                                                SendByte(RecData[i]);
//                                                        }
                                
        }
}
沙发
llljh|  楼主 | 2015-8-15 17:24 | 只看该作者
射频收到数据了,软串口接收没反应,液晶屏没显示,怎么一个定时器,一个外部中断,感觉有问题,不知道怎么用

使用特权

评论回复
板凳
dingy| | 2015-8-15 17:24 | 只看该作者
19200 的通讯速率,每位的传输时间为 52.08uS。

使用特权

评论回复
地板
llljh|  楼主 | 2015-8-15 17:25 | 只看该作者
用外部中断监控下降沿——起始位,1/19200秒,之后1/9600秒,不知道怎么实现的

使用特权

评论回复
5
pengf| | 2015-8-15 17:25 | 只看该作者

在下降沿中断中启动定时器,设定定时器时间值,使其在 26.04uS 后中断。

时间达到 26.04uS 后后,将采样到起始位数据,在定时器中断中设定写器,使其在 52.08uS 后中断,时间达到后,再次采样端口电平。采样共计 10 次,完成一帧数据的接收。

在最后一位数据采集完成后,关定时器中断,打开端口下降沿中断,准备监视下一次起始位的开始。

使用特权

评论回复
6
renyaq| | 2015-8-15 17:25 | 只看该作者

当然,你也可以不要起始位数据,在下降沿中断中,将定时器设置为 52.08uS + 26.04uS 后中断,直接采样第 1 位数据,这样,只需采样 9 次就可以了。

使用特权

评论回复
7
supernan| | 2015-8-15 17:26 | 只看该作者
一步一步来吧,先把显示搞好,再搞中断,再搞模拟串口...

使用特权

评论回复
8
栩栩如生| | 2015-8-15 17:26 | 只看该作者
程序太长,没看。
模拟串口:一个外部中断 + 一个定时器。 注意第一个方波的时间大于后面方波的时间

使用特权

评论回复
9
llljh|  楼主 | 2015-8-15 17:26 | 只看该作者
我的数据在哪个中断里面进行接收判断?我把接收的数据放到数组里面,停止位和起始位我不用管它,那停止位我要了干嘛?

使用特权

评论回复
10
houcs| | 2015-8-15 17:27 | 只看该作者
我说的已经很明白,在下降沿中断中判断起始位,在定时中断中完成接收,停止位一定要接收,但可以不存储,否则,无法界定下一个起始位。

使用特权

评论回复
11
llljh|  楼主 | 2015-8-15 17:27 | 只看该作者
恩,搞定了,哈哈,总算是搞明白了,现在准备搞一个接收仪的整体程序了,压力大啊,刚接触1个月。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

855

主题

11301

帖子

6

粉丝