找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4880|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

單片機unsigned char定義的buzz on數(shù)據(jù)長度是多少

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:214628 發(fā)表于 2017-11-14 14:58 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
如代碼所示,我通過串口發(fā)送buzz on,7蜂鳴器不響,試過buzz on,6buzz on,12buzz on,14buzz on,24buzz on,28buzz on,48buzz on,56都返回bad command.代碼老師說沒有問題,請問buzz on數(shù)據(jù)長度是多少?我應(yīng)該發(fā)送buzz on,?請問該如何解決?
  1. //串口
  2. #include <reg52.h>

  3. bit flagFrame = 0;  //幀接收完成標(biāo)志,即接收到一幀新數(shù)據(jù)
  4. bit flagTxd = 0;    //單字節(jié)發(fā)送完成標(biāo)志,用來替代TXD中斷標(biāo)志位
  5. unsigned char cntRxd = 0;   //接收字節(jié)計數(shù)器
  6. unsigned char pdata bufRxd[64];  //接收字節(jié)緩沖區(qū)

  7. extern void UartAction(unsigned char *buf, unsigned char len);

  8. /* 串口配置函數(shù),baud-通信波特率 */
  9. void ConfigUART(unsigned int baud)
  10. {
  11.     SCON  = 0x50;  //配置串口為模式1
  12.     TMOD &= 0x0F;  //清零T1的控制位
  13.     TMOD |= 0x20;  //配置T1為模式2
  14.     TH1 = 256 - (11059200/12/32)/baud;  //計算T1重載值
  15.     TL1 = TH1;     //初值等于重載值
  16.     ET1 = 0;       //禁止T1中斷
  17.     ES  = 1;       //使能串口中斷
  18.     TR1 = 1;       //啟動T1
  19. }
  20. /* 串口數(shù)據(jù)寫入,即串口發(fā)送函數(shù),buf-待發(fā)送數(shù)據(jù)的指針,len-指定的發(fā)送長度 */
  21. void UartWrite(unsigned char *buf, unsigned char len)
  22. {
  23.     while (len--)  //循環(huán)發(fā)送所有字節(jié)
  24.     {
  25.         flagTxd = 0;      //清零發(fā)送標(biāo)志
  26.         SBUF = *buf++;    //發(fā)送一個字節(jié)數(shù)據(jù)
  27.         while (!flagTxd); //等待該字節(jié)發(fā)送完成
  28.     }
  29. }
  30. /* 串口數(shù)據(jù)讀取函數(shù),buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度 */
  31. unsigned char UartRead(unsigned char *buf, unsigned char len)
  32. {
  33.     unsigned char i;
  34.    
  35.     if (len > cntRxd)  //指定讀取長度大于實際接收到的數(shù)據(jù)長度時,
  36.     {                  //讀取長度設(shè)置為實際接收到的數(shù)據(jù)長度
  37.         len = cntRxd;
  38.     }
  39.     for (i=0; i<len; i++)  //拷貝接收到的數(shù)據(jù)到接收指針上
  40.     {
  41.         *buf++ = bufRxd[i];
  42.     }
  43.     cntRxd = 0;  //接收計數(shù)器清零
  44.    
  45.     return len;  //返回實際讀取長度
  46. }
  47. /* 串口接收監(jiān)控,由空閑時間判定幀結(jié)束,需在定時中斷中調(diào)用,ms-定時間隔 */
  48. void UartRxMonitor(unsigned char ms)
  49. {
  50.     static unsigned char cntbkp = 0;
  51.     static unsigned char idletmr = 0;

  52.     if (cntRxd > 0)  //接收計數(shù)器大于零時,監(jiān)控總線空閑時間
  53.     {
  54.         if (cntbkp != cntRxd)  //接收計數(shù)器改變,即剛接收到數(shù)據(jù)時,清零空閑計時
  55.         {
  56.             cntbkp = cntRxd;
  57.             idletmr = 0;
  58.         }
  59.         else                   //接收計數(shù)器未改變,即總線空閑時,累積空閑時間
  60.         {
  61.             if (idletmr < 30)  //空閑計時小于30ms時,持續(xù)累加
  62.             {
  63.                 idletmr += ms;
  64.                 if (idletmr >= 30)  //空閑時間達(dá)到30ms時,即判定為一幀接收完畢
  65.                 {
  66.                     flagFrame = 1;  //設(shè)置幀接收完成標(biāo)志
  67.                 }
  68.             }
  69.         }
  70.     }
  71.     else
  72.     {
  73.         cntbkp = 0;
  74.     }
  75. }
  76. /* 串口驅(qū)動函數(shù),監(jiān)測數(shù)據(jù)幀的接收,調(diào)度功能函數(shù),需在主循環(huán)中調(diào)用 */
  77. void UartDriver()
  78. {
  79.     unsigned char len;
  80.     unsigned char pdata buf[40];

  81.     if (flagFrame) //有命令到達(dá)時,讀取處理該命令
  82.     {
  83.         flagFrame = 0;
  84.         len = UartRead(buf, sizeof(buf));  //將接收到的命令讀取到緩沖區(qū)中
  85.         UartAction(buf, len);  //傳遞數(shù)據(jù)幀,調(diào)用動作執(zhí)行函數(shù)
  86.     }
  87. }
  88. /* 串口中斷服務(wù)函數(shù) */
  89. void InterruptUART() interrupt 4
  90. {
  91.     if (RI)  //接收到新字節(jié)
  92.     {
  93.         RI = 0;  //清零接收中斷標(biāo)志位
  94.         if (cntRxd < sizeof(bufRxd)) //接收緩沖區(qū)尚未用完時,
  95.         {                            //保存接收字節(jié),并遞增計數(shù)器
  96.             bufRxd[cntRxd++] = SBUF;
  97.         }
  98.     }
  99.     if (TI)  //字節(jié)發(fā)送完畢
  100.     {
  101.         TI = 0;   //清零發(fā)送中斷標(biāo)志位
  102.         flagTxd = 1;  //設(shè)置字節(jié)發(fā)送完成標(biāo)志
  103.     }
  104. }
  105. //LCD1602
  106. #include <reg52.h>

  107. #define LCD1602_DB  P0
  108. sbit LCD1602_RS = P2^5;
  109. sbit LCD1602_RW = P2^6;
  110. sbit LCD1602_E  = P2^7;

  111. /* 等待液晶準(zhǔn)備好 */
  112. void LcdWaitReady()
  113. {
  114.     unsigned char sta;
  115.    
  116.     LCD1602_DB = 0xFF;
  117.     LCD1602_RS = 0;
  118.     LCD1602_RW = 1;
  119.     do {
  120.         LCD1602_E = 1;
  121.         sta = LCD1602_DB; //讀取狀態(tài)字
  122.         LCD1602_E = 0;
  123.     } while (sta & 0x80); //bit7等于1表示液晶正忙,重復(fù)檢測直到其等于0為止
  124. }
  125. /* 向LCD1602液晶寫入一字節(jié)命令,cmd-待寫入命令值 */
  126. void LcdWriteCmd(unsigned char cmd)
  127. {
  128.     LcdWaitReady();
  129.     LCD1602_RS = 0;
  130.     LCD1602_RW = 0;
  131.     LCD1602_DB = cmd;
  132.     LCD1602_E  = 1;
  133.     LCD1602_E  = 0;
  134. }
  135. /* 向LCD1602液晶寫入一字節(jié)數(shù)據(jù),dat-待寫入數(shù)據(jù)值 */
  136. void LcdWriteDat(unsigned char dat)
  137. {
  138.     LcdWaitReady();
  139.     LCD1602_RS = 1;
  140.     LCD1602_RW = 0;
  141.     LCD1602_DB = dat;
  142.     LCD1602_E  = 1;
  143.     LCD1602_E  = 0;
  144. }
  145. /* 設(shè)置顯示RAM起始地址,亦即光標(biāo)位置,(x,y)-對應(yīng)屏幕上的字符坐標(biāo) */
  146. void LcdSetCursor(unsigned char x, unsigned char y)
  147. {
  148.     unsigned char addr;
  149.    
  150.     if (y == 0)  //由輸入的屏幕坐標(biāo)計算顯示RAM的地址
  151.         addr = 0x00 + x;  //第一行字符地址從0x00起始
  152.     else
  153.         addr = 0x40 + x;  //第二行字符地址從0x40起始
  154.     LcdWriteCmd(addr | 0x80);  //設(shè)置RAM地址
  155. }
  156. /* 在液晶上顯示字符串,(x,y)-對應(yīng)屏幕上的起始坐標(biāo),str-字符串指針 */
  157. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  158. {
  159.     LcdSetCursor(x, y);   //設(shè)置起始地址
  160.     while (*str != '\0')  //連續(xù)寫入字符串?dāng)?shù)據(jù),直到檢測到結(jié)束符
  161.     {
  162.         LcdWriteDat(*str++);
  163.     }
  164. }
  165. /* 區(qū)域清除,清除從(x,y)坐標(biāo)起始的len個字符位 */
  166. void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
  167. {
  168.     LcdSetCursor(x, y);   //設(shè)置起始地址
  169.     while (len--)         //連續(xù)寫入空格
  170.     {
  171.         LcdWriteDat(' ');
  172.     }
  173. }
  174. /* 初始化1602液晶 */
  175. void InitLcd1602()
  176. {
  177.     LcdWriteCmd(0x38);  //16*2顯示,5*7點陣,8位數(shù)據(jù)接口
  178.     LcdWriteCmd(0x0C);  //顯示器開,光標(biāo)關(guān)閉
  179.     LcdWriteCmd(0x06);  //文字不動,地址自動+1
  180.     LcdWriteCmd(0x01);  //清屏
  181. }
  182. //主函數(shù)
  183. #include <reg52.h>

  184. sbit BUZZ = P1^0;  //蜂鳴器控制引腳
  185. sbit led  = P1^1;
  186. bit flagBuzzOn = 0;   //蜂鳴器啟動標(biāo)志
  187. unsigned char T0RH = 0;  //T0重載值的高字節(jié)
  188. unsigned char T0RL = 0;  //T0重載值的低字節(jié)

  189. void ConfigTimer0(unsigned int ms);
  190. extern void UartDriver();
  191. extern void ConfigUART(unsigned int baud);
  192. extern void UartRxMonitor(unsigned char ms);
  193. extern void UartWrite(unsigned char *buf, unsigned char len);
  194. extern void InitLcd1602();
  195. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  196. extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);

  197. void main()
  198. {
  199.     EA = 1;            //開總中斷
  200.     ConfigTimer0(1);   //配置T0定時1ms
  201.     ConfigUART(9600);  //配置波特率為9600
  202.     InitLcd1602();     //初始化液晶
  203.     LcdShowStr(0, 1, "Welcome to KST51");
  204.        
  205.         //BUZZ = 0;
  206.         //flagBuzzOn = 1;
  207.     while (1)
  208.     {
  209.         UartDriver();  //調(diào)用串口驅(qū)動
  210.     }
  211. }
  212. /* 內(nèi)存比較函數(shù),比較兩個指針?biāo)赶虻膬?nèi)存數(shù)據(jù)是否相同,
  213.    ptr1-待比較指針1,ptr2-待比較指針2,len-待比較長度
  214.    返回值-兩段內(nèi)存數(shù)據(jù)完全相同時返回1,不同返回0 */
  215. bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)
  216. {
  217.     while (len--)
  218.     {
  219.         if (*ptr1++ != *ptr2++)  //遇到不相等數(shù)據(jù)時即刻返回0
  220.         {
  221.             return 0;
  222.         }
  223.     }
  224.     return 1;  //比較完全部長度數(shù)據(jù)都相等則返回1
  225. }
  226. /* 串口動作函數(shù),根據(jù)接收到的命令幀執(zhí)行響應(yīng)的動作
  227.    buf-接收到的命令幀指針,len-命令幀長度 */
  228. void UartAction(unsigned char *buf, unsigned char len)
  229. {
  230.     unsigned char i;
  231.     unsigned char code cmd0[] = "buzz on";   //開蜂鳴器命令
  232.     unsigned char code cmd1[] = "buzz off";  //關(guān)蜂鳴器命令
  233.     unsigned char code cmd2[] = "showstr ";  //字符串顯示命令
  234.     unsigned char code cmdLen[] = {          //命令長度匯總表
  235.         sizeof(cmd0)-1, sizeof(cmd1)-1, sizeof(cmd2)-1,
  236.     };
  237.     unsigned char code *cmdPtr[] = {         //命令指針匯總表
  238.         &cmd0[0],  &cmd1[0],  &cmd2[0],
  239.     };

  240.     for (i=0; i<sizeof(cmdLen); i++)  //遍歷命令列表,查找相同命令
  241.     {
  242.         if (len >= cmdLen[i])  //首先接收到的數(shù)據(jù)長度要不小于命令長度
  243.         {
  244.             if (CmpMemory(buf, cmdPtr[i], cmdLen[i]))  //比較相同時退出循環(huán)
  245.             {
  246.                 break;
  247.             }
  248.         }
  249.     }
  250.     switch (i)  //循環(huán)退出時i的值即是當(dāng)前命令的索引值
  251.     {
  252.         case 0:
  253.             flagBuzzOn = 1; //開啟蜂鳴器
  254.                         led = 0;
  255.             break;
  256.         case 1:
  257.             flagBuzzOn = 0; //關(guān)閉蜂鳴器
  258.             break;
  259.         case 2:
  260.             buf[len] = '\0';  //為接收到的字符串添加結(jié)束符
  261.             LcdShowStr(0, 0, buf+cmdLen[2]);  //顯示命令后的字符串
  262.             i = len - cmdLen[2];              //計算有效字符個數(shù)
  263.             if (i < 16)  //有效字符少于16時,清除液晶上的后續(xù)字符位
  264.             {
  265.                 LcdAreaClear(i, 0, 16-i);
  266.             }
  267.             break;
  268.         default:   //未找到相符命令時,給上機發(fā)送“錯誤命令”的提示
  269.             UartWrite("bad command.\r\n", sizeof("bad command.\r\n")-1);
  270.             return;
  271.     }
  272.     buf[len++] = '\r';  //有效命令被執(zhí)行后,在原命令幀之后添加
  273.     buf[len++] = '\n';  //回車換行符后返回給上位機,表示已執(zhí)行
  274.     UartWrite(buf, len);
  275. }
  276. /* 配置并啟動T0,ms-T0定時時間 */
  277. void ConfigTimer0(unsigned int ms)
  278. {
  279.     unsigned long tmp;  //臨時變量
  280.    
  281.     tmp = 11059200 / 12;      //定時器計數(shù)頻率
  282.     tmp = (tmp * ms) / 1000;  //計算所需的計數(shù)值
  283.     tmp = 65536 - tmp;        //計算定時器重載值
  284.     tmp = tmp + 33;           //補償中斷響應(yīng)延時造成的誤差
  285.     T0RH = (unsigned char)(tmp>>8);  //定時器重載值拆分為高低字節(jié)
  286.     T0RL = (unsigned char)tmp;
  287.     TMOD &= 0xF0;   //清零T0的控制位
  288.     TMOD |= 0x01;   //配置T0為模式1
  289.     TH0 = T0RH;     //加載T0重載值
  290.     TL0 = T0RL;
  291.     ET0 = 1;        //使能T0中斷
  292.     TR0 = 1;        //啟動T0
  293. }
  294. /* T0中斷服務(wù)函數(shù),執(zhí)行串口接收監(jiān)控和蜂鳴器驅(qū)動 */
  295. void InterruptTimer0() interrupt 1
  296. {
  297.     TH0 = T0RH;  //重新加載重載值
  298.     TL0 = T0RL;
  299.     if (flagBuzzOn)  //執(zhí)行蜂鳴器鳴叫或關(guān)閉
  300.         BUZZ = ~BUZZ;
  301.     else
  302.         BUZZ = 1;
  303.     UartRxMonitor(1);  //串口接收監(jiān)控
  304. }
復(fù)制代碼


QQ截圖20171114104923.png (35.01 KB, 下載次數(shù): 110)

QQ截圖20171114104923.png

QQ截圖20171114142514.png (45.42 KB, 下載次數(shù): 111)

QQ截圖20171114142514.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表