久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4969|回復: 0
收起左側

單片機unsigned char定義的buzz on數據長度是多少

[復制鏈接]
ID:214628 發表于 2017-11-14 14:58 | 顯示全部樓層 |閱讀模式
如代碼所示,我通過串口發送buzz on,7蜂鳴器不響,試過buzz on,6buzz on,12buzz on,14buzz on,24buzz on,28buzz on,48buzz on,56都返回bad command.代碼老師說沒有問題,請問buzz on數據長度是多少?我應該發送buzz on,?請問該如何解決?
  1. //串口
  2. #include <reg52.h>

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

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

  8. /* 串口配置函數,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. /* 串口數據寫入,即串口發送函數,buf-待發送數據的指針,len-指定的發送長度 */
  21. void UartWrite(unsigned char *buf, unsigned char len)
  22. {
  23.     while (len--)  //循環發送所有字節
  24.     {
  25.         flagTxd = 0;      //清零發送標志
  26.         SBUF = *buf++;    //發送一個字節數據
  27.         while (!flagTxd); //等待該字節發送完成
  28.     }
  29. }
  30. /* 串口數據讀取函數,buf-接收指針,len-指定的讀取長度,返回值-實際讀到的長度 */
  31. unsigned char UartRead(unsigned char *buf, unsigned char len)
  32. {
  33.     unsigned char i;
  34.    
  35.     if (len > cntRxd)  //指定讀取長度大于實際接收到的數據長度時,
  36.     {                  //讀取長度設置為實際接收到的數據長度
  37.         len = cntRxd;
  38.     }
  39.     for (i=0; i<len; i++)  //拷貝接收到的數據到接收指針上
  40.     {
  41.         *buf++ = bufRxd[i];
  42.     }
  43.     cntRxd = 0;  //接收計數器清零
  44.    
  45.     return len;  //返回實際讀取長度
  46. }
  47. /* 串口接收監控,由空閑時間判定幀結束,需在定時中斷中調用,ms-定時間隔 */
  48. void UartRxMonitor(unsigned char ms)
  49. {
  50.     static unsigned char cntbkp = 0;
  51.     static unsigned char idletmr = 0;

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

  81.     if (flagFrame) //有命令到達時,讀取處理該命令
  82.     {
  83.         flagFrame = 0;
  84.         len = UartRead(buf, sizeof(buf));  //將接收到的命令讀取到緩沖區中
  85.         UartAction(buf, len);  //傳遞數據幀,調用動作執行函數
  86.     }
  87. }
  88. /* 串口中斷服務函數 */
  89. void InterruptUART() interrupt 4
  90. {
  91.     if (RI)  //接收到新字節
  92.     {
  93.         RI = 0;  //清零接收中斷標志位
  94.         if (cntRxd < sizeof(bufRxd)) //接收緩沖區尚未用完時,
  95.         {                            //保存接收字節,并遞增計數器
  96.             bufRxd[cntRxd++] = SBUF;
  97.         }
  98.     }
  99.     if (TI)  //字節發送完畢
  100.     {
  101.         TI = 0;   //清零發送中斷標志位
  102.         flagTxd = 1;  //設置字節發送完成標志
  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. /* 等待液晶準備好 */
  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; //讀取狀態字
  122.         LCD1602_E = 0;
  123.     } while (sta & 0x80); //bit7等于1表示液晶正忙,重復檢測直到其等于0為止
  124. }
  125. /* 向LCD1602液晶寫入一字節命令,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液晶寫入一字節數據,dat-待寫入數據值 */
  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. /* 設置顯示RAM起始地址,亦即光標位置,(x,y)-對應屏幕上的字符坐標 */
  146. void LcdSetCursor(unsigned char x, unsigned char y)
  147. {
  148.     unsigned char addr;
  149.    
  150.     if (y == 0)  //由輸入的屏幕坐標計算顯示RAM的地址
  151.         addr = 0x00 + x;  //第一行字符地址從0x00起始
  152.     else
  153.         addr = 0x40 + x;  //第二行字符地址從0x40起始
  154.     LcdWriteCmd(addr | 0x80);  //設置RAM地址
  155. }
  156. /* 在液晶上顯示字符串,(x,y)-對應屏幕上的起始坐標,str-字符串指針 */
  157. void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
  158. {
  159.     LcdSetCursor(x, y);   //設置起始地址
  160.     while (*str != '\0')  //連續寫入字符串數據,直到檢測到結束符
  161.     {
  162.         LcdWriteDat(*str++);
  163.     }
  164. }
  165. /* 區域清除,清除從(x,y)坐標起始的len個字符位 */
  166. void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
  167. {
  168.     LcdSetCursor(x, y);   //設置起始地址
  169.     while (len--)         //連續寫入空格
  170.     {
  171.         LcdWriteDat(' ');
  172.     }
  173. }
  174. /* 初始化1602液晶 */
  175. void InitLcd1602()
  176. {
  177.     LcdWriteCmd(0x38);  //16*2顯示,5*7點陣,8位數據接口
  178.     LcdWriteCmd(0x0C);  //顯示器開,光標關閉
  179.     LcdWriteCmd(0x06);  //文字不動,地址自動+1
  180.     LcdWriteCmd(0x01);  //清屏
  181. }
  182. //主函數
  183. #include <reg52.h>

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

  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();  //調用串口驅動
  210.     }
  211. }
  212. /* 內存比較函數,比較兩個指針所指向的內存數據是否相同,
  213.    ptr1-待比較指針1,ptr2-待比較指針2,len-待比較長度
  214.    返回值-兩段內存數據完全相同時返回1,不同返回0 */
  215. bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)
  216. {
  217.     while (len--)
  218.     {
  219.         if (*ptr1++ != *ptr2++)  //遇到不相等數據時即刻返回0
  220.         {
  221.             return 0;
  222.         }
  223.     }
  224.     return 1;  //比較完全部長度數據都相等則返回1
  225. }
  226. /* 串口動作函數,根據接收到的命令幀執行響應的動作
  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";  //關蜂鳴器命令
  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])  //首先接收到的數據長度要不小于命令長度
  243.         {
  244.             if (CmpMemory(buf, cmdPtr[i], cmdLen[i]))  //比較相同時退出循環
  245.             {
  246.                 break;
  247.             }
  248.         }
  249.     }
  250.     switch (i)  //循環退出時i的值即是當前命令的索引值
  251.     {
  252.         case 0:
  253.             flagBuzzOn = 1; //開啟蜂鳴器
  254.                         led = 0;
  255.             break;
  256.         case 1:
  257.             flagBuzzOn = 0; //關閉蜂鳴器
  258.             break;
  259.         case 2:
  260.             buf[len] = '\0';  //為接收到的字符串添加結束符
  261.             LcdShowStr(0, 0, buf+cmdLen[2]);  //顯示命令后的字符串
  262.             i = len - cmdLen[2];              //計算有效字符個數
  263.             if (i < 16)  //有效字符少于16時,清除液晶上的后續字符位
  264.             {
  265.                 LcdAreaClear(i, 0, 16-i);
  266.             }
  267.             break;
  268.         default:   //未找到相符命令時,給上機發送“錯誤命令”的提示
  269.             UartWrite("bad command.\r\n", sizeof("bad command.\r\n")-1);
  270.             return;
  271.     }
  272.     buf[len++] = '\r';  //有效命令被執行后,在原命令幀之后添加
  273.     buf[len++] = '\n';  //回車換行符后返回給上位機,表示已執行
  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;      //定時器計數頻率
  282.     tmp = (tmp * ms) / 1000;  //計算所需的計數值
  283.     tmp = 65536 - tmp;        //計算定時器重載值
  284.     tmp = tmp + 33;           //補償中斷響應延時造成的誤差
  285.     T0RH = (unsigned char)(tmp>>8);  //定時器重載值拆分為高低字節
  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中斷服務函數,執行串口接收監控和蜂鳴器驅動 */
  295. void InterruptTimer0() interrupt 1
  296. {
  297.     TH0 = T0RH;  //重新加載重載值
  298.     TL0 = T0RL;
  299.     if (flagBuzzOn)  //執行蜂鳴器鳴叫或關閉
  300.         BUZZ = ~BUZZ;
  301.     else
  302.         BUZZ = 1;
  303.     UartRxMonitor(1);  //串口接收監控
  304. }
復制代碼


QQ截圖20171114104923.png
QQ截圖20171114142514.png
回復

使用道具 舉報

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

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩中文一区 | 亚洲精品国产电影 | 国产一二三区电影 | 日本成人中文字幕在线观看 | 欧美精品在线视频 | 亚洲网视频 | 狠狠狠 | 久久久蜜臀国产一区二区 | 国产精品777一区二区 | 欧美精三区欧美精三区 | 91精品国产综合久久久久久 | 久久精品亚洲国产奇米99 | 91精品国产91久久久久青草 | 欧美一区两区 | 国产 亚洲 网红 主播 | 久久久久亚洲精品国产 | 免费xxxx大片国产在线 | 日本久久精品视频 | 国产精品亚洲第一 | 2023亚洲天堂 | 国产精品久久国产精品 | 找个黄色片 | 久久国产精品久久久久久 | 午夜精品久久久 | 国产一级毛片视频 | 成人av网站在线观看 | 天堂在线91 | 国产一区2区 | 久久久精品视频免费看 | 成年无码av片在线 | 久久久91 | a视频在线| 欧美视频在线观看 | 一区二区成人在线 | 一级一级毛片免费看 | 日本激情视频在线播放 | 日韩色图视频 | 亚洲一区免费视频 | 黑人成人网 | 久久久91精品国产一区二区精品 | 99r在线 |