|
#include"STC15W4K.H"
#define RECEIVE_MAX_BUTES 1 //最大接收字節(jié)數(shù)
unsigned char RecvBuf[16]; //接收數(shù)據(jù)緩沖區(qū)
unsigned char RecvCount=0; //接收數(shù)據(jù)計(jì)數(shù)器
sbit T_TXD=P3^2; //發(fā)送數(shù)據(jù)引腳
sbit R_RXD=P3^3; //接收數(shù)據(jù)引腳
bit RXD_OK; //數(shù)據(jù)接收完成標(biāo)志,1接收正確 ,0接收錯(cuò)誤
void delay104us()
{
unsigned char i,j,k;
for(i=1;i>0;i--) // 注意后面沒(méi)分號(hào)
for(j=3;j>0;j--) // 注意后面沒(méi)分號(hào)
for(k=189;k>0;k--); // 注意后面有分號(hào)
}
void delay52uS() // 起始位結(jié)束后52uS采樣數(shù)據(jù)
{
unsigned char i,j,k;
for(i=1;i>0;i--) // 注意后面沒(méi)分號(hào)
for(j=3;j>0;j--) // 注意后面沒(méi)分號(hào)
for(k=93;k>0;k--); // 注意后面有分號(hào)
}
voidsenbyte(unsigned char dat)
{
unsigned char i=8; //發(fā)送8位數(shù)據(jù)
T_TXD =0; //發(fā)送起始位
delay104us();
while(i--)
{
if(dat&1) T_TXD=1;
else T_TXD=0;
delay104us();
dat>>=1;
}
T_TXD=1; //發(fā)送停止位
delay104us();
}
unsigned char recvbyte()
{
unsigned char i;
unsigned char dat=0; //接收到的數(shù)據(jù)
RXD_OK=0; //字節(jié)數(shù)據(jù)接收正常標(biāo)志位
delay52us(); //數(shù)據(jù)位中心位置讀取數(shù)據(jù)
if(R_RXD==0) //確認(rèn)起始位正常
{
delay104us(); //起始位寬度
for(i=0;i<8;i++)
{
if(R_RXD) dat|=(1<<i);
delay104us();
}
if(R_RXD==1) //確認(rèn)停止位正常
{
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) //不斷檢測(cè)是否有起始位出現(xiàn)
{
recvbuf[recvcount]=recvbyte();
if(RXD_OK ==1) //一個(gè)字節(jié)接收正常
{
recvcount++;
if(recvcount>=RECEIVE_MAX_BYTES)
{
recvcount=0;
for(i=0;i<RECEIVE_MAX_BYTES;i++)
{
sendbyte( RecvBuf+1); //接收到的數(shù)據(jù)+1后發(fā)回
}
}
}
}
}
}
這是一個(gè)IO引腳模擬串口通信的程序。
接收時(shí)先判斷P3.3接收端口是否有起始位低電平出現(xiàn),如有則按照低位在前的順序接收8位數(shù)據(jù),最后判斷是否有停止位高電平出現(xiàn),如有則完成一個(gè)字節(jié)的接收,否則繼續(xù)等待。P3.2發(fā)送。
其中軟件編寫(xiě)要嚴(yán)格按照異步通信的時(shí)序進(jìn)行,每位傳送時(shí)間按通信速率9600bps計(jì)算為(1/9600)s=104.2us。時(shí)鐘:22.1184M。
這個(gè)程序也看了很久,重點(diǎn)是發(fā)送和接收函數(shù)。
發(fā)送函數(shù)比較好理解,接收函數(shù)不太容易。
迷惑的地方是: if(R_RXD) dat|=(1<<i);
1.為什么要左移,不是先發(fā)送低位的嗎?左移以后先發(fā)送的不就成高位了?
2.為什么要dat為什么要或1,或1以后接收的值不就變了?
其實(shí)是沒(méi)看明白這個(gè)語(yǔ)句:if(R_RXD) dat|=(1<<i);
這樣的格式很容易讓我忽視if(R_RXD)去只思考dat|=(1<<i);
沒(méi)有實(shí)踐就沒(méi)有發(fā)言權(quán),拋棄條件去思考結(jié)果,就是耍流氓,肯定是思考不出結(jié)果的。
這條語(yǔ)句說(shuō)的是如果R_RXD==1,那么dat當(dāng)前為就置1。
另外1<<i,是指1左移i位,而不是i左移1位,同樣的錯(cuò)誤真的很容易再犯,習(xí)慣性思維害人。
另:
#define RECEIVE_MAX_BUTES 1 //最大接收字節(jié)數(shù)
這條宏語(yǔ)句的值改成2后,輸出的結(jié)果并不是想像的那樣。
例如我輸入11 22 點(diǎn)擊發(fā)送,我認(rèn)為會(huì)回復(fù):12 23;實(shí)際上第一次點(diǎn)擊發(fā)送時(shí)串口助手是沒(méi)有接收信息的(接收窗口空白),點(diǎn)擊第二次才會(huì)接收到正確回復(fù)。
這是因?yàn)?/font>
for(i=0;i<RECEIVE_MAX_BYTES;i++)
{
sendbyte( RecvBuf+1); //接收到的數(shù)據(jù)+1后發(fā)回 }
這條語(yǔ)句的原因。
改成條件語(yǔ)句:
SendByte(RecvBuf+1); // 接收到得數(shù)據(jù)+1后發(fā)回
i++;
if(i>=RECEIVE_MAX_BYTES)
{
i=0;
}
自認(rèn)為會(huì)完成改善,其實(shí)結(jié)果是點(diǎn)擊一次發(fā)送,接收到的只有一個(gè)字節(jié)的內(nèi)容,第一次接收到12,第二次接收到23,再點(diǎn)就是12,再是23。
經(jīng)思考:如果想點(diǎn)擊一次發(fā)送,接收到所有發(fā)送內(nèi)容,需要增加發(fā)送數(shù)組函數(shù),調(diào)用現(xiàn)有發(fā)送函數(shù)將發(fā)送內(nèi)容存儲(chǔ)到數(shù)組中,main()函數(shù)中調(diào)用發(fā)送數(shù)組函數(shù)。語(yǔ)句沒(méi)有寫(xiě),所以暫時(shí)只用語(yǔ)言描述。
|
|