|
|
大致就是根據電腦發送的不同命令執行相關操作,并且每次把接收到的命令原封不動發回給電腦,作為接收到命令的標志,但串口調試助手接收不到發回的命令,單片機也沒執行相關操作,目前我想解決串口調試助手接收不到發回的命令的這一問題,請大佬幫忙看看,程序中有部分函數是關于LCD1602的,他們的原形在另一個.c文件中,由于無關且就沒貼出來
屏幕截圖 2021-10-30 165052.png (62.99 KB, 下載次數: 45)
下載附件
2021-10-30 16:53 上傳
單片機源程序如下:
/******UART.c的程序******/
#include "reg52.h"
bit flagFrame = 0;//用于判斷命令是否接收完成的標志
bit flagTxd = 0;//字節發送完成的標志
unsigned char cntRxd = 0;//計數接收到多少字節
unsigned char bufRxd[32];//接收緩沖區
extern void UartAction(unsigned char *buf,unsigned char len);
/**波特率配置函數**/
void ConfigUART(unsigned char baud)
{
SCON = 0x50;
TMOD &= 0x0f;
TMOD |= 0x20;
TH1 = 256 - (11059200/12/32)/baud;;
TL1 = TH1;
ET1 = 0;
ES = 1;
TR1 = 1;
}
/**UART讀取函數,在判斷完命令接收完成后使用,將讀取到的數據從bufRxd中取出**/
unsigned char UartRead(unsigned char *buf,unsigned char len)
{
unsigned char i;
if(len > cntRxd)
{
len = cntRxd;
}
for(i = 0;i < len;i++)
{
*buf++ = bufRxd[ i];
}
cntRxd = 0;
return len;
}
/**命令監測函數,用于監測命令是否接收完成,在中斷中使用**/
void UartRxMonitor(unsigned char ms)
{
static unsigned char cntbkp;//數據接收字節備份值,30ms接收字節與備份值不變,即認為命令接收完成
static unsigned char idletmr;
if(cntRxd > 0)
{
if(cntbkp != cntRxd)
{
cntbkp = cntRxd;
idletmr = 0;
}
else
{
if(idletmr < 30)
idletmr+=ms;
if(idletmr >= 30)
flagFrame = 1;
}
}
else
{
cntbkp = 0;
}
}
/**將接收到的原原本本發送回去,作為接收到了的標志**/
void UartWrite(unsigned char *buf,unsigned char len)
{
while(len--)
{
flagTxd = 0;
SBUF = *buf++;
while(!flagTxd);
}
}
void UartDriver()
{
unsigned char len;
unsigned char buf[40];
if(flagFrame)
{
flagFrame = 0;
len = UartRead(buf,sizeof(buf));
UartAction(buf,len);
}
}
/**UART中斷函數**/
void InterruptUART() interrupt 4
{
if(RI)
{
RI = 0;
if(cntRxd < sizeof(bufRxd))
bufRxd[cntRxd++] = SBUF;
}
if(TI)
{
TI = 0;
flagTxd = 1;
}
}
/******main.c的程序******/
#include "reg52.h"
sbit BUZZ = P2^5;
bit flagBuzzOn = 0;
unsigned char T0RH = 0;
unsigned char T0RL = 0;
void ConfigTimer0(unsigned int ms);
extern void ConfigUART(unsigned char baud);
extern unsigned char UartRead(unsigned char *buf,unsigned char len);
extern void UartRxMonitor(unsigned char ms);
extern void UartWrite(unsigned char *buf,unsigned char len);
extern void UartDriver();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
extern void InitLcd1602();
void main()
{
EA = 1;
ConfigTimer0(1);
ConfigUART(9600);
InitLcd1602();
LcdShowStr(0, 0, "Welcome to 51");
while(1)
{
UartDriver();
}
}
/**命令比較函數,將接收的命令與現有的命令進行比較**/
bit CmpMemory(unsigned char *ptr1,unsigned char *ptr2,unsigned char len)
{
while(len--)
{
if(*ptr1++ != *ptr2++)
{
return 0;
}
}
return 1;
}
/**根據接收到的命令執行不同的操作**/
void UartAction(unsigned char *buf,unsigned char len)
{
unsigned char i;
unsigned char code cmd0[] = "buzz on";
unsigned char code cmd1[] = "buzz off";
unsigned char code cmd2[] = "showstr ";
unsigned char code cmdlen[] = {
sizeof(cmd0)-1,sizeof(cmd1)-1,sizeof(cmd2)-1
};
unsigned char *cmdPtr[] = {&cmd0[0],&cmd1[0],&cmd2[0]};
for(i = 0;i < 3;i++)
{
if(len >= cmdlen[ i])
{
if(CmpMemory(buf,cmdPtr[ i],cmdlen[ i]))
{
break;
}
}
}
switch(i)
{
case(0):
flagBuzzOn = 1;
break;
case(1):
flagBuzzOn = 0;
break;
case(2):
buf[len] = '\0';
LcdShowStr(0,0,buf+cmdlen[2]);
i = len-cmdlen[2];
if(i < 16)
{
LcdAreaClear(i,0,16-i);
}
break;
default:
UartWrite("erro.\r\n",sizeof("erro.\r\n")-1);
return;
}
buf[len++] = '\r';
buf[len++] = '\n';
UartWrite(buf,len);
}
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數頻率
tmp = (tmp * ms) / 1000; //計算所需的計數值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 33; //補償中斷響應延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 為模式 1
TH0 = T0RH; //加載 T0 重載值
TL0 = T0RL;
ET0 = 1; //使能 T0 中斷
TR0 = 1; //啟動 T0
}
/**在中斷中調用UartRxMonitor(ms)函數,來記錄沒有接收到新命令的時間,超過30ms就認為命令已經接收完整**/
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
if (flagBuzzOn) //執行蜂鳴器鳴叫或關閉
BUZZ = ~BUZZ;
else
BUZZ = 1;
UartRxMonitor(1); //串口接收監控
}
|
|