|
如代碼所示,我通過串口發(fā)送buzz on,7蜂鳴器不響,試過buzz on,6buzz on,12buzz on,14buzz on,24buzz on,28buzz on,48buzz on,56都返回bad command.代碼老師說沒有問題,請(qǐng)問buzz on數(shù)據(jù)長度是多少?我應(yīng)該發(fā)送buzz on,?請(qǐng)問該如何解決?- //串口
- #include <reg52.h>
- bit flagFrame = 0; //幀接收完成標(biāo)志,即接收到一幀新數(shù)據(jù)
- bit flagTxd = 0; //單字節(jié)發(fā)送完成標(biāo)志,用來替代TXD中斷標(biāo)志位
- unsigned char cntRxd = 0; //接收字節(jié)計(jì)數(shù)器
- unsigned char pdata bufRxd[64]; //接收字節(jié)緩沖區(qū)
- extern void UartAction(unsigned char *buf, unsigned char len);
- /* 串口配置函數(shù),baud-通信波特率 */
- void ConfigUART(unsigned int baud)
- {
- SCON = 0x50; //配置串口為模式1
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x20; //配置T1為模式2
- TH1 = 256 - (11059200/12/32)/baud; //計(jì)算T1重載值
- TL1 = TH1; //初值等于重載值
- ET1 = 0; //禁止T1中斷
- ES = 1; //使能串口中斷
- TR1 = 1; //啟動(dòng)T1
- }
- /* 串口數(shù)據(jù)寫入,即串口發(fā)送函數(shù),buf-待發(fā)送數(shù)據(jù)的指針,len-指定的發(fā)送長度 */
- void UartWrite(unsigned char *buf, unsigned char len)
- {
- while (len--) //循環(huán)發(fā)送所有字節(jié)
- {
- flagTxd = 0; //清零發(fā)送標(biāo)志
- SBUF = *buf++; //發(fā)送一個(gè)字節(jié)數(shù)據(jù)
- while (!flagTxd); //等待該字節(jié)發(fā)送完成
- }
- }
- /* 串口數(shù)據(jù)讀取函數(shù),buf-接收指針,len-指定的讀取長度,返回值-實(shí)際讀到的長度 */
- unsigned char UartRead(unsigned char *buf, unsigned char len)
- {
- unsigned char i;
-
- if (len > cntRxd) //指定讀取長度大于實(shí)際接收到的數(shù)據(jù)長度時(shí),
- { //讀取長度設(shè)置為實(shí)際接收到的數(shù)據(jù)長度
- len = cntRxd;
- }
- for (i=0; i<len; i++) //拷貝接收到的數(shù)據(jù)到接收指針上
- {
- *buf++ = bufRxd[i];
- }
- cntRxd = 0; //接收計(jì)數(shù)器清零
-
- return len; //返回實(shí)際讀取長度
- }
- /* 串口接收監(jiān)控,由空閑時(shí)間判定幀結(jié)束,需在定時(shí)中斷中調(diào)用,ms-定時(shí)間隔 */
- void UartRxMonitor(unsigned char ms)
- {
- static unsigned char cntbkp = 0;
- static unsigned char idletmr = 0;
- if (cntRxd > 0) //接收計(jì)數(shù)器大于零時(shí),監(jiān)控總線空閑時(shí)間
- {
- if (cntbkp != cntRxd) //接收計(jì)數(shù)器改變,即剛接收到數(shù)據(jù)時(shí),清零空閑計(jì)時(shí)
- {
- cntbkp = cntRxd;
- idletmr = 0;
- }
- else //接收計(jì)數(shù)器未改變,即總線空閑時(shí),累積空閑時(shí)間
- {
- if (idletmr < 30) //空閑計(jì)時(shí)小于30ms時(shí),持續(xù)累加
- {
- idletmr += ms;
- if (idletmr >= 30) //空閑時(shí)間達(dá)到30ms時(shí),即判定為一幀接收完畢
- {
- flagFrame = 1; //設(shè)置幀接收完成標(biāo)志
- }
- }
- }
- }
- else
- {
- cntbkp = 0;
- }
- }
- /* 串口驅(qū)動(dòng)函數(shù),監(jiān)測數(shù)據(jù)幀的接收,調(diào)度功能函數(shù),需在主循環(huán)中調(diào)用 */
- void UartDriver()
- {
- unsigned char len;
- unsigned char pdata buf[40];
- if (flagFrame) //有命令到達(dá)時(shí),讀取處理該命令
- {
- flagFrame = 0;
- len = UartRead(buf, sizeof(buf)); //將接收到的命令讀取到緩沖區(qū)中
- UartAction(buf, len); //傳遞數(shù)據(jù)幀,調(diào)用動(dòng)作執(zhí)行函數(shù)
- }
- }
- /* 串口中斷服務(wù)函數(shù) */
- void InterruptUART() interrupt 4
- {
- if (RI) //接收到新字節(jié)
- {
- RI = 0; //清零接收中斷標(biāo)志位
- if (cntRxd < sizeof(bufRxd)) //接收緩沖區(qū)尚未用完時(shí),
- { //保存接收字節(jié),并遞增計(jì)數(shù)器
- bufRxd[cntRxd++] = SBUF;
- }
- }
- if (TI) //字節(jié)發(fā)送完畢
- {
- TI = 0; //清零發(fā)送中斷標(biāo)志位
- flagTxd = 1; //設(shè)置字節(jié)發(fā)送完成標(biāo)志
- }
- }
- //LCD1602
- #include <reg52.h>
- #define LCD1602_DB P0
- sbit LCD1602_RS = P2^5;
- sbit LCD1602_RW = P2^6;
- sbit LCD1602_E = P2^7;
- /* 等待液晶準(zhǔn)備好 */
- void LcdWaitReady()
- {
- unsigned char sta;
-
- LCD1602_DB = 0xFF;
- LCD1602_RS = 0;
- LCD1602_RW = 1;
- do {
- LCD1602_E = 1;
- sta = LCD1602_DB; //讀取狀態(tài)字
- LCD1602_E = 0;
- } while (sta & 0x80); //bit7等于1表示液晶正忙,重復(fù)檢測直到其等于0為止
- }
- /* 向LCD1602液晶寫入一字節(jié)命令,cmd-待寫入命令值 */
- void LcdWriteCmd(unsigned char cmd)
- {
- LcdWaitReady();
- LCD1602_RS = 0;
- LCD1602_RW = 0;
- LCD1602_DB = cmd;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- /* 向LCD1602液晶寫入一字節(jié)數(shù)據(jù),dat-待寫入數(shù)據(jù)值 */
- void LcdWriteDat(unsigned char dat)
- {
- LcdWaitReady();
- LCD1602_RS = 1;
- LCD1602_RW = 0;
- LCD1602_DB = dat;
- LCD1602_E = 1;
- LCD1602_E = 0;
- }
- /* 設(shè)置顯示RAM起始地址,亦即光標(biāo)位置,(x,y)-對(duì)應(yīng)屏幕上的字符坐標(biāo) */
- void LcdSetCursor(unsigned char x, unsigned char y)
- {
- unsigned char addr;
-
- if (y == 0) //由輸入的屏幕坐標(biāo)計(jì)算顯示RAM的地址
- addr = 0x00 + x; //第一行字符地址從0x00起始
- else
- addr = 0x40 + x; //第二行字符地址從0x40起始
- LcdWriteCmd(addr | 0x80); //設(shè)置RAM地址
- }
- /* 在液晶上顯示字符串,(x,y)-對(duì)應(yīng)屏幕上的起始坐標(biāo),str-字符串指針 */
- void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
- {
- LcdSetCursor(x, y); //設(shè)置起始地址
- while (*str != '\0') //連續(xù)寫入字符串?dāng)?shù)據(jù),直到檢測到結(jié)束符
- {
- LcdWriteDat(*str++);
- }
- }
- /* 區(qū)域清除,清除從(x,y)坐標(biāo)起始的len個(gè)字符位 */
- void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
- {
- LcdSetCursor(x, y); //設(shè)置起始地址
- while (len--) //連續(xù)寫入空格
- {
- LcdWriteDat(' ');
- }
- }
- /* 初始化1602液晶 */
- void InitLcd1602()
- {
- LcdWriteCmd(0x38); //16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
- LcdWriteCmd(0x0C); //顯示器開,光標(biāo)關(guān)閉
- LcdWriteCmd(0x06); //文字不動(dòng),地址自動(dòng)+1
- LcdWriteCmd(0x01); //清屏
- }
- //主函數(shù)
- #include <reg52.h>
- sbit BUZZ = P1^0; //蜂鳴器控制引腳
- sbit led = P1^1;
- bit flagBuzzOn = 0; //蜂鳴器啟動(dòng)標(biāo)志
- unsigned char T0RH = 0; //T0重載值的高字節(jié)
- unsigned char T0RL = 0; //T0重載值的低字節(jié)
- void ConfigTimer0(unsigned int ms);
- extern void UartDriver();
- extern void ConfigUART(unsigned int baud);
- extern void UartRxMonitor(unsigned char ms);
- extern void UartWrite(unsigned char *buf, unsigned char len);
- extern void InitLcd1602();
- extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
- extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
- void main()
- {
- EA = 1; //開總中斷
- ConfigTimer0(1); //配置T0定時(shí)1ms
- ConfigUART(9600); //配置波特率為9600
- InitLcd1602(); //初始化液晶
- LcdShowStr(0, 1, "Welcome to KST51");
-
- //BUZZ = 0;
- //flagBuzzOn = 1;
- while (1)
- {
- UartDriver(); //調(diào)用串口驅(qū)動(dòng)
- }
- }
- /* 內(nèi)存比較函數(shù),比較兩個(gè)指針?biāo)赶虻膬?nèi)存數(shù)據(jù)是否相同,
- ptr1-待比較指針1,ptr2-待比較指針2,len-待比較長度
- 返回值-兩段內(nèi)存數(shù)據(jù)完全相同時(shí)返回1,不同返回0 */
- bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)
- {
- while (len--)
- {
- if (*ptr1++ != *ptr2++) //遇到不相等數(shù)據(jù)時(shí)即刻返回0
- {
- return 0;
- }
- }
- return 1; //比較完全部長度數(shù)據(jù)都相等則返回1
- }
- /* 串口動(dòng)作函數(shù),根據(jù)接收到的命令幀執(zhí)行響應(yīng)的動(dòng)作
- buf-接收到的命令幀指針,len-命令幀長度 */
- void UartAction(unsigned char *buf, unsigned char len)
- {
- unsigned char i;
- unsigned char code cmd0[] = "buzz on"; //開蜂鳴器命令
- unsigned char code cmd1[] = "buzz off"; //關(guān)蜂鳴器命令
- unsigned char code cmd2[] = "showstr "; //字符串顯示命令
- unsigned char code cmdLen[] = { //命令長度匯總表
- sizeof(cmd0)-1, sizeof(cmd1)-1, sizeof(cmd2)-1,
- };
- unsigned char code *cmdPtr[] = { //命令指針匯總表
- &cmd0[0], &cmd1[0], &cmd2[0],
- };
- for (i=0; i<sizeof(cmdLen); i++) //遍歷命令列表,查找相同命令
- {
- if (len >= cmdLen[i]) //首先接收到的數(shù)據(jù)長度要不小于命令長度
- {
- if (CmpMemory(buf, cmdPtr[i], cmdLen[i])) //比較相同時(shí)退出循環(huán)
- {
- break;
- }
- }
- }
- switch (i) //循環(huán)退出時(shí)i的值即是當(dāng)前命令的索引值
- {
- case 0:
- flagBuzzOn = 1; //開啟蜂鳴器
- led = 0;
- break;
- case 1:
- flagBuzzOn = 0; //關(guān)閉蜂鳴器
- break;
- case 2:
- buf[len] = '\0'; //為接收到的字符串添加結(jié)束符
- LcdShowStr(0, 0, buf+cmdLen[2]); //顯示命令后的字符串
- i = len - cmdLen[2]; //計(jì)算有效字符個(gè)數(shù)
- if (i < 16) //有效字符少于16時(shí),清除液晶上的后續(xù)字符位
- {
- LcdAreaClear(i, 0, 16-i);
- }
- break;
- default: //未找到相符命令時(shí),給上機(jī)發(fā)送“錯(cuò)誤命令”的提示
- UartWrite("bad command.\r\n", sizeof("bad command.\r\n")-1);
- return;
- }
- buf[len++] = '\r'; //有效命令被執(zhí)行后,在原命令幀之后添加
- buf[len++] = '\n'; //回車換行符后返回給上位機(jī),表示已執(zhí)行
- UartWrite(buf, len);
- }
- /* 配置并啟動(dòng)T0,ms-T0定時(shí)時(shí)間 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp; //臨時(shí)變量
-
- tmp = 11059200 / 12; //定時(shí)器計(jì)數(shù)頻率
- tmp = (tmp * ms) / 1000; //計(jì)算所需的計(jì)數(shù)值
- tmp = 65536 - tmp; //計(jì)算定時(shí)器重載值
- tmp = tmp + 33; //補(bǔ)償中斷響應(yīng)延時(shí)造成的誤差
- T0RH = (unsigned char)(tmp>>8); //定時(shí)器重載值拆分為高低字節(jié)
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0為模式1
- TH0 = T0RH; //加載T0重載值
- TL0 = T0RL;
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動(dòng)T0
- }
- /* T0中斷服務(wù)函數(shù),執(zhí)行串口接收監(jiān)控和蜂鳴器驅(qū)動(dòng) */
- void InterruptTimer0() interrupt 1
- {
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- if (flagBuzzOn) //執(zhí)行蜂鳴器鳴叫或關(guān)閉
- BUZZ = ~BUZZ;
- else
- BUZZ = 1;
- UartRxMonitor(1); //串口接收監(jiān)控
- }
復(fù)制代碼
|
|