#include"STC15W4K.H"
#define RECEIVE_MAX_BUTES 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--); // 注意后面有分号
}
voidsenbyte(unsigned char dat)
{
unsigned char i=8; //发送8位数据
T_TXD =0; //发送起始位
delay104us();
while(i--)
{
if(dat&1) T_TXD=1;
else T_TXD=0;
delay104us();
dat>>=1;
}
T_TXD=1; //发送停止位
delay104us();
}
unsigned char recvbyte()
{
unsigned char i;
unsigned char dat=0; //接收到的数据
RXD_OK=0; //字节数据接收正常标志位
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;
}
}
return dat;
}
void printfstr(char *pstr) //串口打印字符串
{
while(*pstr)
{
sendbyte(*pstr++);
}
}
void main(void)
{
unsigned char i;
printfstr("模串口:STC15\r\n");
while(1)
{
if(R_RXD==0) //不断检测是否有起始位出现
{
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+1); //接收到的数据+1后发回
}
}
}
}
}
}
这是一个IO引脚模拟串口通信的程序。
接收时先判断P3.3接收端口是否有起始位低电平出现,如有则按照低位在前的顺序接收8位数据,最后判断是否有停止位高电平出现,如有则完成一个字节的接收,否则继续等待。P3.2发送。
其中软件编写要严格按照异步通信的时序进行,每位传送时间按通信速率9600bps计算为(1/9600)s=104.2us。时钟:22.1184M。
这个程序也看了很久,重点是发送和接收函数。
发送函数比较好理解,接收函数不太容易。
迷惑的地方是: if(R_RXD) dat|=(1<<i);
1.为什么要左移,不是先发送低位的吗?左移以后先发送的不就成高位了?
2.为什么要dat为什么要或1,或1以后接收的值不就变了?
其实是没看明白这个语句:if(R_RXD) dat|=(1<<i);
这样的格式很容易让我忽视if(R_RXD)去只思考dat|=(1<<i);
没有实践就没有发言权,抛弃条件去思考结果,就是耍流氓,肯定是思考不出结果的。
这条语句说的是如果R_RXD==1,那么dat当前为就置1。
另外1<<i,是指1左移i位,而不是i左移1位,同样的错误真的很容易再犯,习惯性思维害人。
另:
#define RECEIVE_MAX_BUTES 1 //最大接收字节数
这条宏语句的值改成2后,输出的结果并不是想像的那样。
例如我输入11 22 点击发送,我认为会回复:12 23;实际上第一次点击发送时串口助手是没有接收信息的(接收窗口空白),点击第二次才会接收到正确回复。
这是因为
for(i=0;i<RECEIVE_MAX_BYTES;i++)
{
sendbyte( RecvBuf+1); //接收到的数据+1后发回 }
这条语句的原因。
改成条件语句:
SendByte(RecvBuf+1); // 接收到得数据+1后发回
i++;
if(i>=RECEIVE_MAX_BYTES)
{
i=0;
}
自认为会完成改善,其实结果是点击一次发送,接收到的只有一个字节的内容,第一次接收到12,第二次接收到23,再点就是12,再是23。
经思考:如果想点击一次发送,接收到所有发送内容,需要增加发送数组函数,调用现有发送函数将发送内容存储到数组中,main()函数中调用发送数组函数。语句没有写,所以暂时只用语言描述。
|