标题: 单片机任意I/O口模拟串口的程序,有一句代码不明白 [打印本页]

作者: 1017038201    时间: 2023-12-23 23:24
标题: 单片机任意I/O口模拟串口的程序,有一句代码不明白
请高人帮忙指点,小弟胜感激
/****************《51单片机轻松入门-基于STC15W4K系列》配套例程 *************
/*  任意I/O口模拟串口,22.1184MHZ, 内部R/C时钟,9600bps  */

#include "STC15W4K.H"            // 包含 "STC15W4K.H"寄存器定义头文件  
#define RECEIVE_MAX_BYTES  1     // 最大接收字节数

unsigned char RecvBuf[16];       // 接收数据缓冲区
unsigned char RecvCount=0;       // 接收数据计数器

sbit T_TXD=P3^2;                 // 发送数据的引脚
sbit R_RXD=P3^3;                 // 接收数据的引脚
bit RXD_OK;                         // 数据接收完成标志,1(接收正确),0(接收错误)
//******************************************/
void delay104uS()
{
  unsigned char i,j,k;
  for(i=1;i>0;i--)         // 注意后面没分号
  for(j=3;j>0;j--)         // 注意后面没分号
  for(k=189;k>0;k--);      // 注意后面有分号  
}
void delay52uS()               // 起始位结束后52uS采样数据
{
  unsigned char i,j,k;
  for(i=1;i>0;i--)         // 注意后面没分号
  for(j=3;j>0;j--)         // 注意后面没分号
  for(k=93;k>0;k--);       // 注意后面有分号  
}
void SendByte(unsigned char Dat)
{
       unsignedchar i=8;      // 发送8 位数据
       T_TXD=0;                        // 发送起始位
       delay104uS();
       while(i--)
       {
              if(Dat&1)T_TXD=1;
              elseT_TXD=0;
              delay104uS();
              Dat>>=1;
       }
       T_TXD=1;                        // 发送停止位
       delay104uS();           // 延时   
}

unsigned char RecvByte()
{
       unsignedchar i;      
       unsignedchar Dat=0;            // 接收到的数据
       RXD_OK=0;                              // 字节数据接收正常标志,0——错误,1——正常
       delay52uS();                   // 数据位中心位置读数据   
       if(R_RXD==0)                     // 确认起始位正常
       {   
              delay104uS();               // 起始位宽度            
              for(i=0;i<8;i++)
              {
                     if(R_RXD)     Dat|=(1<<i);  /这一句不懂,求高人讲解。
                     delay104uS();
              }   
              if(R_RXD==1)                // 确认停止位正常
              {
                     RXD_OK=1;
              }
       }  
       returnDat;
}

//功能:串口打印字符串
//*****************************************/
void PrintfStr(char * pstr)
{
       while(*pstr)   
       {
              SendByte(*pstr++);
       }
}

//功能:函数主体
//******************************************/
void main(void)
{  
       unsignedchar i;     
       PrintfStr("模拟串口:STC15\r\n");
       while(1)                  
       {
              if(R_RXD==0)      // 死循环不断检测R_RXD是否有起始位出现
              {
                     RecvBuf[RecvCount]=RecvByte();
                     if(RXD_OK==1)                                     // 一个字节接收正常
                     {  
                            RecvCount++;
                            if(RecvCount>=RECEIVE_MAX_BYTES)
                            {
                                   RecvCount=0;
                                   for(i=0;i<RECEIVE_MAX_BYTES;i++)
                                   {
                                          SendByte(RecvBuf[ i]+1);        // 接收到得数据+1后发回
                                   }
                            }
                     }            
              }
       }
}

作者: wdgao    时间: 2023-12-24 01:19
这里要实现的是把串行收到的数一位一位地接收下来转成并行的8位数,这里只考虑收到是1的情况,没考虑收到0的情况,应该是少了一句程序。
作者: wulin    时间: 2023-12-24 07:30
Dat变量初始为0,用2进制表示:00000000 8位都是0
当for循环,if(R_RXD)判断R_RXD为真,也就是1,
Dat|=(1<<i); 等同Dat=Dat|(1<<i),结果一样写法不同,
这段代码就是把由低到高收到的1按位插入Dat。
例如:
Dat初始=0000 0000
收到字节1010 0101
逐次按位相或后Dat=1010 0101=0xa5
作者: 人中狼    时间: 2023-12-24 08:32
功能如楼上所说,不过DAT初始化为0,所以不考虑接收0的情况
作者: dream2023    时间: 2023-12-24 09:52
表示接收的数据或等于1右移i位
作者: bsjzb    时间: 2023-12-24 10:49
这段代码是使用单片机STC15W4K模拟串口通信的程序。它通过模拟IO口实现了串口的发送和接收功能。  代码中定义了一个接收数据缓冲区RecvBuf和一个接收数据计数器RecvCount。接收到的数据存储在RecvBuf数组中,并根据接收计数器进行处理。  在主函数main中,先发送一条初始化信息"模拟串口:STC15\r\n",然后进入死循环不断检测R_RXD引脚是否有起始位出现。如果检测到起始位,则调用RecvByte函数接收一字节数据,并判断接收是否正常。  如果接收正常,将接收到的数据存储在RecvBuf数组中,并递增接收计数器RecvCount。当接收计数器达到最大接收字节数RECEIVE_MAX_BYTES时,将接收到的数据加1后通过SendByte函数发送回去。  整个程序的功能是模拟串口通信,接收到的数据加1后再发送回去。  需要注意的是,这段代码只是单片机的程序,无法在此环境中直接运行。如果需要运行,请将代码下载到STC15W4K单片机开发板上,并根据硬件连接情况进行相应的配置。
作者: rayin    时间: 2023-12-24 11:16
如果R_RXD=1, 就把Dat=Dat第0 到7 bit(根据i的循环置0-7)置1.
作者: 1017038201    时间: 2023-12-24 19:00
wulin 发表于 2023-12-24 07:30
Dat变量初始为0,用2进制表示:00000000 8位都是0
当for循环,if(R_RXD)判断R_RXD为真,也就是1,
Dat|=( ...

非常感谢这位老师的回复!
只是我感觉这句代码有问题,如果改动一下就对了,也好理解。
if(R_RXD)
Dat |=(i<<1);
作者: man1234567    时间: 2023-12-25 08:16
1017038201 发表于 2023-12-24 19:00
非常感谢这位老师的回复!
只是我感觉这句代码有问题,如果改动一下就对了,也好理解。
if(R_RXD)

没有任何改动哈,回车和缩进对机器可有可无只是方便人类阅读罢了。
将多行放在一行是可行的,只要多行能正常运行放在同一行也一样行。
作者: Graves    时间: 2023-12-28 13:55
1017038201 发表于 2023-12-24 19:00
非常感谢这位老师的回复!
只是我感觉这句代码有问题,如果改动一下就对了,也好理解。
if(R_RXD)

不知道是你复制错了还是故意改的,Dat |=(i<<1);不能这样改,逻辑上错了,还得原本的Dat |=(1<<i);




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1