找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于单片机PWM多级调速控制LED和小型直流电机的问题

[复制链接]
跳转到指定楼层
楼主
环境介绍:硬件部分有LD3320语音识别模块+STC11L56XE+51单片机开发板(普中51-单核-A2)。语音识别模块的程序已经写好了(见下部分),每次输入语音信号后,LD3320模块对应输出口输出一个高电平信号,几十毫秒后,再输出低电平信号(如:我说“开灯”,LD3320将IO口P1.0输出高电平,几十毫秒后再输出低电平,LD3320的P1.0接入51的P2.0);LD3320的P1.0~P1.5和51的P2.0~P2.5已经通过杜邦线连接,51的P2.6口为LED高电平输入口,51的P1.0为风扇的驱动口(相关驱动程序已经写好)。
整个项目的目的是:通过语音识别的方式,控制LED灯开灯(低亮度),高亮度,关灯;控制直流电机开风扇(低速),高速度,关风扇。
问题1:现在的情况是,我输入“亮一点”指令后,LED确实是亮度高的那档,然后输入“开灯”指令后,LED确实是低亮度那档,但是如果我先输入“开灯”指令,LED能低亮度运行,后输入“亮一点”指令后,LED无法到高亮度那档(电机的情况通LED)。
问题2:为什么我输入“关灯”或“关风扇”指令后,LED总会有一点点亮度,电机还会有很微小的转动。

各位老师帮帮孩子吧,一直没想到问题在哪里,如有描述不清的地方,我都会尽快回复的,谢谢各位。

语音识别模块部分程序:
  1. void         User_handle(uint8 dat)
  2. {
  3.      //UARTSendByte(dat);//串口识别码(十六进制)
  4.                  if(0==dat)
  5.                  {
  6.                   G0_flag=ENABLE;
  7.                         LED=0;
  8.                         PrintCom("小智收到\r\n"); /*text.....*/
  9.                  }
  10.                  else if(ENABLE==G0_flag)
  11.                  {        
  12.                                  G0_flag=DISABLE;
  13.                                 LED=1;
  14.                          switch(dat)                   /*对结果执行相关操作,客户可删除Printcom 串口输出语句替换为其他需要控制的代码*/
  15.                           {
  16.                                   case CODE_DMCS:                        
  17.                                                 PrintCom("“开灯”命令识别成功\r\n"); /*text.....*/
  18.                                                 PrintCom("主人,已打开灯\r\n"); /*text.....*/
  19.                                                 P10=1;delay(200);P10=0;
  20.                                                 break;
  21.                                         case CODE_KFBYZ:        
  22.                                                 PrintCom("“亮一点”命令识别成功\r\n"); /*text.....*/
  23.                                                 PrintCom("主人,灯亮度已经变高\r\n"); /*text.....*/
  24.                                                 P11=1;delay(200);P11=0;
  25.                                                 break;
  26.                                         case CODE_KD:                                       
  27.                                                 PrintCom("“关灯”命令识别成功\r\n"); /*text.....*/
  28.                                                 PrintCom("主人,已关闭LED\r\n"); /*text.....*/
  29.                                                 P12=1;delay(200);P12=0;
  30.                                                 break;
  31.                                         case CODE_GD:                                                                                       
  32.                                                 PrintCom("“开风扇”命令识别成功\r\n"); /*text.....*/
  33.                                                 PrintCom("主人,已打开风扇\r\n"); /*text.....*/
  34.                                                 P13=1;delay(200);P13=0;
  35.                                                 break;
  36.                                         case CODE_BJ:                                                
  37.                                                 PrintCom("“快一点”命令识别成功\r\n"); /*text.....*/
  38.                                                 PrintCom("主人,风扇转速已经变高\r\n"); /*text.....*/
  39.                                                 P14=1;delay(200);P14=0;
  40.                                                 break;
  41.                                         case CODE_SH:                                                
  42.                                                 PrintCom("“关风扇”命令识别成功\r\n"); /*text.....*/
  43.                                                  PrintCom("主人,已关闭风扇\r\n"); /*text.....*/
  44.                                                 P15=1;delay(200);P15=0;
  45.                                                 break;
  46.                                         case CODE_GZ:                                       
  47.                                                 PrintCom("“晚安”命令识别成功\r\n"); /*text.....*/
  48.                                                 PrintCom("晚安,主人\r\n"); /*text.....*/
  49.                                                 break;                                                                                                                                                                                                                        
  50.                                                         default:PrintCom("请重新识别发口令\r\n"); /*text.....*/
  51.                                                         break;
  52.                                 }        
  53.                         }        
  54.                         else         
  55.                         {
  56.                                 PrintCom("请说出一级口令\r\n"); /*text.....*/        
  57.                         }
  58. }
复制代码

51单片机代码如下:
  1. #include "reg52.h"                         //此文件中定义了单片机的一些特殊功能寄存器
  2. #include<intrins.h>                //因为要用到左右移函数,所以加入这个头文件

  3. typedef unsigned int u16;          //对数据类型进行声明定义
  4. typedef unsigned char u8;

  5. sbit led1 = P2^0;  //LED标志位1,开启LED和低亮度
  6. sbit led2 = P2^1;  //LED标志位2,高亮度
  7. sbit led3 = P2^2;  //LED标志位3,关闭LED

  8. sbit fengshan1 = P2^3;         //风扇标志位1,开启风扇和低速度
  9. sbit fengshan2 = P2^4;         //风扇标志位2,高速度
  10. sbit fengshan3 = P2^5;         //风扇标志位3,关闭风扇

  11. sbit led =  P2^6;//LED驱动位
  12. sbit fengshan = P1^0; //风扇驱动位

  13. u16 Counter,Compare1,Compare2;        //计数值和比较值,用于输出PWM
  14. u16 led1flag,led2flag,led3flag;
  15. u16 fengshan1flag,fengshan2flag,fengshan3flag;

  16. void delay10ms(void)
  17. {
  18.         unsigned char i,j,k;
  19.         for(i=5;i>0;i--)
  20.          for(j=4;j>0;j--)
  21.           for(k=248;k>0;k--);
  22. }

  23. void LED()
  24. {
  25.         if(led1 == 1)        {led1flag = 1;}
  26.         if(led2 == 1)        {led2flag = 1;}
  27.         if(led3 == 1)        {led3flag = 1;}
  28.                                                                
  29.         if(led1flag == 1)        {Compare1 = 5;led2flag = 0;led3flag = 0;}
  30.         if(led2flag == 1)        {Compare1 = 100;led1flag = 0;led3flag = 0;}
  31.         if(led3flag == 1)        {Compare1 = 0;led1flag = 0;led2flag = 0;}
  32.         
  33. }

  34. void FS()
  35. {
  36.         if(fengshan1 == 1)        {fengshan1flag = 1;}
  37.         if(fengshan2 == 1)        {fengshan2flag = 1;}
  38.         if(fengshan3 == 1)        {fengshan3flag = 1;}

  39.         if(fengshan1flag == 1)         {Compare2 = 40;fengshan2flag = 0;fengshan3flag = 0;}
  40.         if(fengshan2flag == 1)         {Compare2 = 100;fengshan1flag = 0;fengshan3flag = 0;}
  41.         if(fengshan3flag == 1)         {Compare2 = 0;fengshan1flag = 0;fengshan2flag = 0;}        
  42. }

  43. void Timer0_Init(void)
  44. {
  45.         TMOD &= 0xF0;                //设置定时器模式
  46.         TMOD |= 0x01;                //设置定时器模式
  47.         
  48.         TH0 = 0xFF;                    //设置定时初始值   高八位低八位0xFFA4 组成 100us
  49.         TL0 = 0x9C;                    //设置定时初始值
  50.         
  51.         TF0 = 0;                    //清除TF0标志
  52.         TR0 = 1;                    //定时器0开始计时
  53.         ET0=1;                            //允许定时器T0中断
  54.         EA=1;                             //开启总中断
  55.         PT0=0;                             //优先级为低
  56. }

  57. void main()
  58. {
  59.         Timer0_Init();                        //定时器初始化
  60.         P2 = 0;//P2.0-P2.7初始化
  61.         fengshan = 0;

  62.         while(1)
  63.         {        
  64.                 LED();
  65.                 FS();
  66.         }

  67. }

  68. void Timer0() interrupt 1         //进入定时器中断
  69. {
  70.         TH0 = 0xFF;
  71.         TL0 = 0x9C;                    //重新赋初始值
  72.         
  73.         Counter++;                         //计数值自加
  74.         Counter%=100;                 //计数值变化范围限制在0~99

  75.         if(led1flag == 1 || led2flag == 1 || led3flag ==1)
  76.         {
  77.                 if(Counter < Compare1)         //计数值小于比较值
  78.                  {
  79.                          led = 1;        
  80.                  }                                                         
  81.                 else          //计数值大于比较值
  82.                 {
  83.                         led = 0;                                       
  84.                 }               
  85.         }

  86.         if(fengshan1flag == 1||fengshan2flag == 1||fengshan3flag == 1)
  87.         {                          
  88.                 if(Counter < Compare2)         //计数值小于比较值
  89.                  {
  90.                          fengshan = 1;        
  91.                  }                                                         
  92.                 else          //计数值大于比较值
  93.                 {
  94.                         fengshan = 0;                                       
  95.                 }               
  96.         }                                
  97. }
复制代码


语音识别1.png (159.5 KB, 下载次数: 17)

语音识别1.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2022-4-28 12:11 | 只看该作者
与你的硬件结构有关。
上图。
回复

使用道具 举报

板凳
ID:161164 发表于 2022-4-28 13:15 来自手机 | 只看该作者
改为if(led1){Compare1=5……
回复

使用道具 举报

地板
ID:735831 发表于 2022-4-28 13:55 | 只看该作者
为什么要在定时器里做比较再做翻转,既然要稳定的PWM那每做一次判断和io翻转的时间不会更长吗?这边建议进入中断后先不要赋值,万一还没比较完又开始了第二次中断就不好了,可以的话计算,比较等问题放在主函数或者子函数调用会比直接在中断程序中处理更迅速。如果出现微亮那可能是没有关闭中断导致IO存在翻转的情况。可以的话能贴一下原理图和相关引脚输出波形(上示波器看)是最好的了,希望能帮助到楼主
回复

使用道具 举报

5#
ID:735831 发表于 2022-4-28 14:04 | 只看该作者
这里提一下我的看法,定时器中断在不使用的时候关闭就好,占用资源浪费cpu时间。然后微亮可能是楼主硬件问题最好贴一下原理图,这里个人的看法是可能定时器没有关闭导致的进入中断后重复赋值导致的翻转。为什么要在中断里做判断,如果是要做两个不同设备的PWM为什么不用两路定时器,就算只用一路为什么不做标志位回到主函数或者子函数再判断,如果需要进行的运算复杂的话可以做成子函数再调用会比在中断中做三四次判断快得多。最好仔细研究一下你子函数判断次数,优化代码冗余,不要做多余判断
回复

使用道具 举报

6#
ID:882276 发表于 2022-4-28 14:09 | 只看该作者
yzwzfyz 发表于 2022-4-28 12:11
与你的硬件结构有关。
上图。

啊,能不能指出比较具体一点的方向,我好去改一下,谢谢您。
回复

使用道具 举报

7#
ID:882276 发表于 2022-4-28 14:15 | 只看该作者
lkc8210 发表于 2022-4-28 13:15
改为if(led1){Compare1=5……

您好,可以麻烦您说详细点吗,谢谢
回复

使用道具 举报

8#
ID:735831 发表于 2022-4-28 18:46 | 只看该作者
Mr.zxw 发表于 2022-4-28 14:15
您好,可以麻烦您说详细点吗,谢谢

判断的值为这样 if(ture)执行接下来的代码ture可以为变量,只要值为ture(1)都会执行
回复

使用道具 举报

9#
ID:882276 发表于 2022-4-28 21:48 | 只看该作者
hzhehe 发表于 2022-4-28 14:04
这里提一下我的看法,定时器中断在不使用的时候关闭就好,占用资源浪费cpu时间。然后微亮可能是楼主硬件问 ...

谢谢指点,我研究研究
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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