找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4057|回复: 0
打印 上一主题 下一主题
收起左侧

单片机unsigned char定义的buzz on数据长度是多少

[复制链接]
跳转到指定楼层
楼主
如代码所示,我通过串口发送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 (35.01 KB, 下载次数: 102)

QQ截图20171114104923.png

QQ截图20171114142514.png (45.42 KB, 下载次数: 106)

QQ截图20171114142514.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表